async def fetch_role_resource(conn, role_id): """Get a role resource by role_id.""" resource = ( await r.table("roles") .get_all(role_id, index="role_id") .merge( { "id": r.row["role_id"], "owners": fetch_relationships("role_owners", "role_id", role_id), "administrators": fetch_relationships( "role_admins", "role_id", role_id ), "members": fetch_relationships("role_members", "role_id", role_id), "tasks": fetch_relationships("role_tasks", "role_id", role_id), "proposals": fetch_proposal_ids_by_opener(role_id), "packs": fetch_relationships("role_packs", "role_id", role_id), } ) .without("role_id") .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound("Role {} doesn't exist.".format(role_id))
async def fetch_info_by_username(request): username = request.json.get("id") conn = request.app.config.DB_CONN result = ( await r.table("auth") .get_all(username, index="username") .limit(1) .coerce_to("array") .run(conn) ) if result: return result[0] result = ( await r.table("users") .get_all(username, index="username") .limit(1) .coerce_to("array") .run(conn) ) if not result: raise ApiNotFound("No user with username '{}' exists.".format(username)) result = result[0] user_key = Key() encrypted_private_key = encrypt_private_key( request.app.config.AES_KEY, user_key.public_key, user_key.private_key_bytes ) auth_entry = { "user_id": result.get("user_id"), "username": result.get("username"), "email": result.get("email"), "encrypted_private_key": encrypted_private_key, } insert_result = await r.table("auth").insert(auth_entry).run(conn) # TODO: execute USER_ADD_KEY message return auth_entry
async def fetch_user_relationships(conn, user_id, head_block_num): """Database Query to get an individual's surrounding org connections.""" resource = ( await r.table("users") .get_all(user_id, index="user_id") .merge( { "id": r.row["user_id"], "direct_reports": fetch_user_ids_by_manager(user_id, head_block_num), } ) .without( "user_id", "start_block_num", "end_block_num", "metadata", "email", "key", "manager_id", "name", "remote_id", "username", ) .coerce_to("array") .run(conn) ) peers = await fetch_peers(conn, user_id) managers = await fetch_manager_chain(conn, user_id) resource[0]["peers"] = peers resource[0]["managers"] = managers try: return resource[0] except IndexError: raise ApiNotFound("Not Found: No user with the id {} exists".format(user_id))
async def fetch_role_resource(conn, role_id, head_block_num): resource = (await r.table("roles").get_all(role_id, index="role_id").merge({ "id": r.row["role_id"], "owners": fetch_relationships("role_owners", "role_id", role_id, head_block_num), "administrators": fetch_relationships("role_admins", "role_id", role_id, head_block_num), "members": fetch_relationships("role_members", "role_id", role_id, head_block_num), "tasks": fetch_relationships("role_tasks", "role_id", role_id, head_block_num), "proposals": fetch_proposal_ids_by_opener(role_id, head_block_num), "packs": fetch_relationships("role_packs", "role_id", role_id, head_block_num), }).without("role_id").coerce_to("array").run(conn)) try: return resource[0] except IndexError: raise ApiNotFound( "Not Found: No role with the id {} exists".format(role_id))
async def fetch_info_by_user_id(conn, user_id): LOGGER.warning("fetching user with id: %s", user_id) auth_info = await r.table("auth").get(user_id).run(conn) if auth_info is None: raise ApiNotFound("Not Found: " "No user with id '{}' exists.".format(user_id)) return auth_info
async def fetch_task_resource(conn, task_id, head_block_num): resource = ( await r.table("tasks") .get_all(task_id, index="task_id") .filter( (head_block_num >= r.row["start_block_num"]) & (head_block_num < r.row["end_block_num"]) ) .merge( { "id": r.row["task_id"], "owners": fetch_relationships( "task_owners", "task_id", task_id, head_block_num ), "administrators": fetch_relationships( "task_admins", "task_id", task_id, head_block_num ), "roles": fetch_relationships_by_id( "role_tasks", task_id, "role_id", head_block_num ), "proposals": fetch_proposal_ids_by_opener(task_id, head_block_num), } ) .without("task_id") .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound("Not Found: No task with the id {} exists".format(task_id))
async def fetch_user_resource(conn, user_id, head_block_num): resource = ( await r.table("users") .get_all(user_id, index="user_id") .filter( (head_block_num >= r.row["start_block_num"]) & (head_block_num < r.row["end_block_num"]) ) .merge( { "id": r.row["user_id"], "email": r.db("rbac") .table("auth") .filter({"user_id": user_id}) .get_field("email") .coerce_to("array") .nth(0), "subordinates": fetch_user_ids_by_manager(user_id, head_block_num), "ownerOf": r.union( fetch_relationships_by_id( "task_owners", user_id, "task_id", head_block_num ), fetch_relationships_by_id( "role_owners", user_id, "role_id", head_block_num ), ), "administratorOf": r.union( fetch_relationships_by_id( "task_admins", user_id, "task_id", head_block_num ), fetch_relationships_by_id( "role_admins", user_id, "role_id", head_block_num ), ), "memberOf": fetch_relationships_by_id( "role_members", user_id, "role_id", head_block_num ), "proposals": fetch_proposal_ids_by_opener(user_id, head_block_num), } ) .map( lambda user: (user["manager_id"] != "").branch( user.merge({"manager": user["manager_id"]}), user ) ) .map( lambda user: (user["metadata"] == "").branch(user.without("metadata"), user) ) .without("user_id", "manager_id", "start_block_num", "end_block_num") .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound("Not Found: No user with the id {} exists".format(user_id))
async def delete_user_resource(conn, next_id): """Database query to delete an individual user.""" resource = (await r.table("users").filter({ "next_id": next_id }).delete(return_changes=True).run(conn)) try: return resource except IndexError: raise ApiNotFound( "Not Found: No user with the id {} exists".format(next_id))
async def get_auth_by_next_id(next_id): """Get user record from auth table using next_id.""" conn = await create_connection() user_auth = (await r.table("auth").filter({ "next_id": next_id }).coerce_to("array").run(conn)) conn.close() if not user_auth: raise ApiNotFound("No user with id '{}' exists".format(next_id)) return user_auth[0]
async def fetch_info_by_user_name(conn, user_name): auth_info = (await r.table("auth").filter(r.row["user_name"] == user_name ).coerce_to("array").run(conn)) if not auth_info: raise ApiNotFound("Not Found: " "No user with name '{}' exists.".format(user_name)) LOGGER.warning(auth_info[0]) return auth_info[0]
async def fetch_recommended_resources(conn, identifier, head_block_num, start, limit): resource = (await r.table("roles").outer_join( r.table("role_members"), lambda a, b: a["role_id"].eq(b["role_id"]) ).zip().filter(lambda c: c.has_fields("identifiers").not_() | c["identifiers"].contains(identifier).not_()).slice( start, start + limit).coerce_to("array").run(conn)) try: return resource[0] except IndexError: raise ApiNotFound( "Not Found: No role without identifier {}".format(identifier))
async def fetch_user_resource(conn, user_id, head_block_num): """Database query to get data on an individual user.""" resource = ( await r.table("users") .get_all(user_id, index="user_id") .merge( { "id": r.row["user_id"], "name": r.row["name"], "email": r.row["email"], "subordinates": fetch_user_ids_by_manager(user_id, head_block_num), "ownerOf": { "tasks": fetch_relationships_by_id( "task_owners", user_id, "task_id", head_block_num ), "roles": fetch_relationships_by_id( "role_owners", user_id, "role_id", head_block_num ), "packs": fetch_relationships_by_id( "pack_owners", user_id, "pack_id", head_block_num ), }, "administratorOf": { "tasks": fetch_relationships_by_id( "task_admins", user_id, "task_id", head_block_num ), "roles": fetch_relationships_by_id( "role_admins", user_id, "role_id", head_block_num ), }, "memberOf": fetch_relationships_by_id( "role_members", user_id, "role_id", head_block_num ), "expired": fetch_expired_roles(user_id), "proposals": fetch_proposal_ids_by_opener(user_id, head_block_num), } ) .map( lambda user: (user["manager_id"] != "").branch( user.merge({"manager": user["manager_id"]}), user ) ) .map( lambda user: (user["metadata"] == "").branch(user.without("metadata"), user) ) .without("user_id", "manager_id", "start_block_num", "end_block_num") .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound("Not Found: No user with the id {} exists".format(user_id))
async def fetch_block_by_num(conn, block_num): try: return (await r.table("blocks").get(block_num).merge({ "id": r.row["block_id"], "num": r.row["block_num"] }).without("block_id", "block_num").run(conn)) except ReqlRuntimeError: raise ApiNotFound( "Not Found: " "No block with the block num '{}' exists.".format(block_num))
async def get_user_by_username(request): """Get user information from users table by username.""" username = request.json.get("id") conn = await create_connection() user = (await r.table("users").filter(lambda doc: (doc["username"].match( "(?i)^" + username + "$"))).coerce_to("array").run(conn)) conn.close() if len(user) == 1: return user[0] if user: LOGGER.warning("User logged in with a duplicate username: %s", username) raise ApiNotFound("Login error. Contact an Administrator.")
async def fetch_recommended_resources(conn, identifier, head_block_num, start, limit): resource = (await r.table("role_members").filter( lambda doc: doc["identifiers"].contains(identifier).not_() & (head_block_num >= doc["start_block_num"]) & (head_block_num < doc["end_block_num"])).slice( start, start + limit).get_field("role_id").coerce_to("array").run(conn)) try: return resource[0] except IndexError: raise ApiNotFound( "Not Found: No role without identifier {}".format(identifier))
async def fetch_block_by_id(conn, block_id): resource = (await r.table("blocks").get_all(block_id, index="block_id").merge({ "id": r.row["block_id"], "num": r.row["block_num"] }).without("block_id", "block_num").coerce_to("array").run(conn)) try: return resource[0] except IndexError: raise ApiNotFound( "Not Found: No block with the id '{}' exists.".format(block_id))
async def fetch_user_resource_summary(conn, user_id, head_block_num): """Database query to get summary data on an individual user.""" resource = ( await r.table("users") .get_all(user_id, index="user_id") .merge({"id": r.row["user_id"], "name": r.row["name"], "email": r.row["email"]}) .without("user_id", "manager_id", "start_block_num", "end_block_num") .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound("Not Found: No user with the id {} exists".format(user_id))
async def fetch_pack_resource(conn, pack_id, head_block_num): """Get a pack resource""" resource = (await r.table("packs").get_all(pack_id, index="pack_id").merge({ "id": r.row["pack_id"], "roles": fetch_relationships_by_id("role_packs", pack_id, "role_id", head_block_num), }).without("pack_id").coerce_to("array").run(conn)) try: return resource[0] except IndexError: raise ApiNotFound( "Not Found: No pack with the id {} exists".format(pack_id))
async def fetch_pack_resource(conn, pack_id): """Get a pack resource""" resource = (await r.table("packs").get_all(pack_id, index="pack_id").merge({ "id": r.row["pack_id"], "roles": fetch_relationships_by_id("role_packs", pack_id, "role_id"), "owners": fetch_relationships("pack_owners", "pack_id", pack_id), }).without("pack_id").coerce_to("array").run(conn)) try: return resource[0] except IndexError: raise ApiNotFound("Pack {} doesn't exist.".format(pack_id))
async def fetch_info_by_username(request): username = request.json.get("id") conn = await db_utils.create_connection( request.app.config.DB_HOST, request.app.config.DB_PORT, request.app.config.DB_NAME, ) result = (await r.table("auth").get_all( username, index="username").limit(1).coerce_to("array").run(conn)) if result: return result[0] # Auth record not found, check if the username exists result = (await r.table("users").get_all( username, index="username").limit(1).coerce_to("array").run(conn)) if not result: raise ApiNotFound( "No user with username '{}' exists.".format(username)) result = result[0] # Generate and store key and auth record first time a user logs in user_id = result.get("user_id") user_key = Key() batch_list = rbac.key.batch_list( signer_keypair=user_key, signer_user_id=user_id, user_id=user_id, key_id=user_key.public_key, ) await utils.send(request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT) encrypted_private_key = encrypt_private_key(request.app.config.AES_KEY, user_key.public_key, user_key.private_key_bytes) auth_entry = { "user_id": user_id, "username": result.get("username"), "email": result.get("email"), "encrypted_private_key": encrypted_private_key, } await r.table("auth").insert(auth_entry).run(conn) conn.close() return auth_entry
async def fetch_proposal_resource(conn, proposal_id, head_block_num): resource = ( await r.table("proposals") .get_all(proposal_id, index="proposal_id") .filter( (head_block_num >= r.row["start_block_num"]) & (head_block_num < r.row["end_block_num"]) ) .map( lambda proposal: proposal.merge( { "id": proposal["proposal_id"], "type": proposal["proposal_type"], "object": proposal["object_id"], "target": proposal["target_id"], } ) ) .map( lambda proposal: (proposal["metadata"] == "").branch( proposal.without("metadata"), proposal ) ) .without( "start_block_num", "end_block_num", "proposal_id", "proposal_type", "object_id", "target_id", ) .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound( "Not Found: No proposal with the id {} exists".format(proposal_id) )
async def fetch_dn_by_username(request): """Given a login request, return the user's AD Distinguished Name. Args: request (dict): The login request containing an id, password, and app configurations. """ username = request.json.get("id") conn = await db_utils.create_connection( request.app.config.DB_HOST, request.app.config.DB_PORT, request.app.config.DB_NAME, ) result = (await r.table("users").filter(lambda doc: (doc["username"].match( "(?i)^" + username + "$"))).limit(1).coerce_to("array").run(conn)) if not result: raise ApiNotFound("The username you entered is incorrect.") result = result[0] user_dn = result.get("user_id") conn.close() return user_dn
async def fetch_user_resource_summary(conn, next_id): """Database query to get summary data on an individual user.""" if "cn" in next_id.lower(): user_attribute = "distinguished_name" else: user_attribute = "next_id" resource = ( await r.table("users") .filter(lambda user: (user[user_attribute] == next_id)) .merge( { "id": r.row[user_attribute], "name": r.row["name"], "email": r.row["email"], } ) .without(user_attribute, "manager_id", "start_block_num", "end_block_num") .coerce_to("array") .run(conn) ) try: return resource[0] except IndexError: raise ApiNotFound("Not Found: No user with the id {} exists".format(next_id))
async def delete_role(request, role_id): """Delete a role by it's next_id. Args: role_id: str: the role_id field of the targeted role Returns: json: dict: { message: str: the status of the role delete operation deleted: int: count of the number of roles that were deleted } Raises: ApiForbidden: The user is not a system admin or owner of the targeted role. ApiNotFound: The role does not exist in RethinkDB. ApiInternalError: There was an error compiling blockchain transactions. """ txn_key, txn_user_id = await utils.get_transactor_key(request) # does the role exist? if not await roles_query.does_role_exist(request.app.config.DB_CONN, role_id): LOGGER.warning( "Nonexistent Role – User %s is attempting to delete the nonexistent role %s", txn_user_id, role_id, ) return await handle_not_found( request, ApiNotFound("The targeted role does not exist.") ) is_role_owner = await check_role_owner_status(txn_user_id, role_id) if not is_role_owner: is_admin = await check_admin_status(txn_user_id) if not is_admin: LOGGER.warning( "Permission Denied – User %s does not have sufficient privilege to delete role %s.", txn_user_id, role_id, ) return await handle_errors( request, ApiForbidden("You do not have permission to delete this role.") ) txn_list = [] txn_list = await create_rjct_ppsls_role_txns( txn_key, role_id, txn_user_id, txn_list ) txn_list = await create_del_admin_by_role_txns(txn_key, role_id, txn_list) txn_list = await create_del_mmbr_by_role_txns(txn_key, role_id, txn_list) txn_list = await create_del_ownr_by_role_txns(txn_key, role_id, txn_list) txn_list = create_del_role_txns(txn_key, role_id, txn_list) # validate transaction list if not txn_list: LOGGER.warning( "txn_list is empty. There was an error processing the delete role transactions. Transaction list: %s", txn_list, ) return await handle_errors( request, ApiInternalError( "An error occurred while creating the blockchain transactions to delete the role." ), ) batch = batcher.make_batch_from_txns(transactions=txn_list, signer_keypair=txn_key) batch_list = batcher.batch_to_list(batch=batch) await utils.send( request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT ) return json( {"message": "Role {} successfully deleted".format(role_id), "deleted": 1} )
def auth_via_azure(user_map): """Authorize via Azure credentials to access NEXT.""" # TODO: Implement Azure authentication LOGGER.info("Azure authorization not implemented %s not authorized.", user_map) raise ApiNotFound("Auth source not implemented")
async def fetch_info_by_user_id(conn, user_id): auth_info = await r.table("auth").get(user_id).run(conn) if not auth_info: raise ApiNotFound("No user with id '{}' exists.".format(user_id)) return auth_info