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)
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)
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()
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
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
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
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
def do_test_impersonation_forbidden(): with self.app.app_context(): session["user"] = {"uid": "urn:nope", "admin": False} confirm_allow_impersonation()