Example #1
0
def other():
    confirm_allow_impersonation()

    uid = query_param("uid")
    user = _user_query().filter(User.uid == uid).one()
    # avoid 2fa registration / validation
    return _user_json_response(user, True)
Example #2
0
def me():
    headers = current_request.headers
    user_id = current_user_id()

    impersonate_id = headers.get("X-IMPERSONATE-ID", default=None, type=int)
    if impersonate_id:
        confirm_allow_impersonation(confirm_feature_impersonation_allowed=False)

    return _user_activity(user_id)
Example #3
0
    def test_is_admin(self):
        with self.app.app_context():
            session["user"] = {"uid": "urn:john", "admin": True, "confirmed_admin": True}

            self.assertTrue(is_admin_user({"uid": "urn:john"}))
            self.assertTrue(is_application_admin())

            confirm_allow_impersonation()
            request_context.is_authorized_api_call = False
            confirm_write_access()
Example #4
0
    def test_impersonation_forbidden_by_configuration(self):
        def do_test_impersonation_forbidden():
            with self.app.app_context():
                session["user"] = {"uid": "urn:nope", "admin": True, "confirmed_admin": True}
                confirm_allow_impersonation()

        with self.app.app_context():
            session["user"] = {"uid": "urn:nope", "admin": True, "confirmed_admin": True}
            self.app.app_config.feature.impersonation_allowed = False
            confirm_allow_impersonation(confirm_feature_impersonation_allowed=False)

        self.assertRaises(Forbidden, do_test_impersonation_forbidden)
        self.app.app_config.feature.impersonation_allowed = True
Example #5
0
def collaboration_search():
    confirm_allow_impersonation()

    res = []
    q = query_param("q")
    if q and len(q):
        base_query = "SELECT id, name, description, organisation_id FROM collaborations "
        not_wild_card = "*" not in q
        if not_wild_card:
            q = replace_full_text_search_boolean_mode_chars(q)
            base_query += f"WHERE MATCH (name, description) AGAINST (:q IN BOOLEAN MODE) " \
                          f"AND id > 0 ORDER BY NAME LIMIT {full_text_search_autocomplete_limit}"
        sql = text(base_query if not_wild_card else base_query + " ORDER BY NAME")
        if not_wild_card:
            sql = sql.bindparams(bindparam("q", type_=String))
        result_set = db.engine.execute(sql, {"q": f"{q}*"}) if not_wild_card else db.engine.execute(sql)
        res = [{"id": row[0], "name": row[1], "description": row[2], "organisation_id": row[3]} for row in result_set]
    return res, 200
Example #6
0
def update_user():
    headers = current_request.headers
    user_id = current_user_id()

    impersonate_id = headers.get("X-IMPERSONATE-ID", default=None, type=int)
    if impersonate_id:
        confirm_allow_impersonation()

    user = User.query.get(user_id)
    user_json = current_request.get_json()

    validate_ip_networks(user_json, networks_name="user_ip_networks")

    ip_networks_json = [nw for nw in user_json["user_ip_networks"]] if "user_ip_networks" in user_json else []
    user_ip_network_ids = [network["id"] for network in ip_networks_json if "id" in network and network["id"]]
    for network in user.user_ip_networks:
        if network.id not in user_ip_network_ids:
            db.session.delete(network)
        else:
            existing_network = next(n for n in ip_networks_json if int(n.get("id", -1)) == network.id)
            network.network_value = existing_network["network_value"]
            db.session.merge(network)
    new_networks = [network for network in ip_networks_json if "id" not in network or not network["id"]]
    audit_trail = {"created_by": user.uid, "updated_by": user.uid}
    for network in new_networks:
        db.session.merge(UserIpNetwork(**{**network, **{"user_id": user.id}, **audit_trail}))

    ssh_keys_json = [ssh_key for ssh_key in user_json["ssh_keys"] if
                     ssh_key["ssh_value"]] if "ssh_keys" in user_json else []
    for ssh_key in ssh_keys_json:
        ssh_value = ssh_key["ssh_value"]
        if ssh_value and (ssh_value.startswith("---- BEGIN SSH2 PUBLIC KEY ----")
                          or ssh_value.startswith("-----BEGIN PUBLIC KEY-----")  # noQA:W503
                          or ssh_value.startswith("-----BEGIN RSA PUBLIC KEY-----")):  # noQA:W503
            with tempfile.NamedTemporaryFile() as f:
                f.write(ssh_value.encode())
                f.flush()
                options = ["ssh-keygen", "-i", "-f", f.name]
                if ssh_value.startswith("-----BEGIN PUBLIC KEY-----"):
                    options.append("-mPKCS8")
                if ssh_value.startswith("-----BEGIN RSA PUBLIC KEY-----"):
                    options.append("-mPEM")
                res = subprocess.run(options, stdout=subprocess.PIPE)
                if res.returncode == 0:
                    ssh_key["ssh_value"] = res.stdout.decode()

    ssh_key_ids = [ssh_key["id"] for ssh_key in ssh_keys_json if "id" in ssh_key]
    for ssh_key in user.ssh_keys:
        if ssh_key.id not in ssh_key_ids:
            db.session.delete(ssh_key)
        else:
            existing_ssh_key = next(s for s in ssh_keys_json if int(s.get("id", -1)) == ssh_key.id)
            ssh_key.ssh_value = "".join(
                ch for ch in existing_ssh_key["ssh_value"] if unicodedata.category(ch)[0] != "C")
            db.session.merge(ssh_key)
    new_ssh_keys = [ssh_key for ssh_key in ssh_keys_json if "id" not in ssh_key]
    for ssh_key in new_ssh_keys:
        ssh_value = "".join(ch for ch in ssh_key["ssh_value"] if unicodedata.category(ch)[0] != "C")
        db.session.merge(SshKey(ssh_value=ssh_value, user_id=user.id))

    user.updated_by = user.uid
    db.session.merge(user)
    db.session.commit()
    return user, 201
Example #7
0
def user_search():
    confirm_allow_impersonation()

    q = query_param("q")
    organisation_id = query_param("organisation_id", required=False)
    collaboration_id = query_param("collaboration_id", required=False)
    organisation_admins = query_param("organisation_admins", required=False)
    collaboration_admins = query_param("collaboration_admins", required=False)

    base_query = "SELECT u.id, u.uid, u.name, u.email, o.name, om.role, c.name, cm.role  FROM users u "

    organisation_join = " INNER " if organisation_id or organisation_admins else "LEFT "
    base_query += f"{organisation_join} JOIN organisation_memberships om ON om.user_id = u.id " \
                  f"{organisation_join} JOIN organisations o ON o.id = om.organisation_id "

    collaboration_join = " INNER " if collaboration_id or collaboration_admins else "LEFT "
    base_query += f"{collaboration_join} JOIN collaboration_memberships cm ON cm.user_id = u.id " \
                  f"{collaboration_join} JOIN collaborations c ON c.id = cm.collaboration_id "

    base_query += " WHERE 1=1 "
    not_wild_card = q != "*"
    if not_wild_card:
        q = replace_full_text_search_boolean_mode_chars(q)
        base_query += "AND MATCH (u.name, u.email) AGAINST (:q IN BOOLEAN MODE) " \
                      "AND u.id > 0 "

    if organisation_id:
        base_query += f"AND om.organisation_id = {int(organisation_id)} "

    if collaboration_id:
        base_query += f"AND cm.collaboration_id = {int(collaboration_id)} "

    if organisation_admins:
        base_query += "AND om.role = 'admin'"

    if collaboration_admins:
        base_query += "AND cm.role = 'admin'"

    base_query += f" ORDER BY u.name  LIMIT {full_text_search_autocomplete_limit}"

    sql = text(base_query)

    if not_wild_card:
        sql = sql.bindparams(bindparam("q", type_=String))
    result_set = db.engine.execute(sql, {"q": f"{q}*"}) if not_wild_card else db.engine.execute(sql)
    data = [{"id": row[0], "uid": row[1], "name": row[2], "email": row[3], "organisation_name": row[4],
             "organisation_role": row[5], "collaboration_name": row[6],
             "collaboration_role": row[7]} for row in result_set]

    res = []
    for key, group in itertools.groupby(data, lambda u: u["id"]):
        user_info = {"id": key, "organisations": [], "collaborations": []}
        for g in group:
            user_info["uid"] = g["uid"]
            user_info["name"] = g["name"]
            user_info["email"] = g["email"]
            user_info["admin"] = is_admin_user(g)
            if g["organisation_name"] is not None and g["organisation_name"] not in [item["name"] for item in
                                                                                     user_info["organisations"]]:
                user_info["organisations"].append({"name": g["organisation_name"], "role": g["organisation_role"]})
            if g["collaboration_name"] is not None and g["collaboration_name"] not in [item["name"] for item in
                                                                                       user_info["collaborations"]]:
                user_info["collaborations"].append({"name": g["collaboration_name"], "role": g["collaboration_role"]})
        res.append(user_info)
    return res, 200
Example #8
0
 def do_test_impersonation_forbidden():
     with self.app.app_context():
         session["user"] = {"uid": "urn:nope", "admin": False}
     confirm_allow_impersonation()