def admin_userpermission_change(token, u_id, permission_id): """Given a User by their user ID, set their permissions to new permissions described by permission_id""" permission_id = int(permission_id) # Check validity if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) if not validator.is_valid_user(u_id): raise ValueError(INVALID_USER) if permission_id not in [OWNER, ADMIN, MEMBER]: raise ValueError(INVALID_PERM_ID) # Get users user_acting = database.get_user_by_id(jwt_handler.decode_token(token)) user_target = database.get_user_by_id(u_id) # Check that token has valid permissions for this permission id, then make # the change if user_acting["permission"] == OWNER: # Owners can do anything database.update_user_by_id(u_id, {"permission": permission_id}) elif user_acting["permission"] == ADMIN and\ user_target["permission"] != OWNER and\ permission_id != OWNER: database.update_user_by_id(u_id, {"permission": permission_id}) else: raise AccessError(NO_PERMISSION) return {}
def standup_collect(token, channel_id): """Collect and collate standup messages, returns collated message""" if not is_standup_running(channel_id): u_id = jwt_handler.decode_token(token) starter = database.get_user_by_id(u_id) standup_info = database.get_standup_channel_info(channel_id) output_msg = f"STANDUP SUMMARY. Started By: {starter['handle']}. " +\ f"Length: {standup_info['length']}seconds\n\n" +\ f"MESSAGES:\n" for message in standup_info["messages"]: user = database.get_user_by_id(message["u_id"]) output_msg = output_msg + f"{user['handle']}: " output_msg = output_msg + f"{message['message']}\n" database.wipe_standup_messages(channel_id) return output_msg return None
def message_unpin(token, message_id): """Given a message within a channel, remove it's mark as unpinned""" # Validate token if not validator.is_valid_token(token): raise ValueError(INVALID_TOKEN) # Decode token u_id = jwt_handler.decode_token(token) user = database.get_user_by_id(u_id) message = database.get_message_by_id(message_id) if message is None: raise ValueError(MESSAGE_UNPIN_NOT_EXIST) channel = database.get_channel_by_id(message["channel_id"]) if user["permission"] not in [OWNER, ADMIN] \ and u_id not in channel["owner_ids"]: raise AccessError(MESSAGE_UNPIN_NO_AUTH) # Checking data if u_id not in channel["auth_ids"]: raise AccessError(CHANNEL_CANT_VIEW_DETAIL) if message["is_pinned"] is False: raise ValueError(MESSAGE_NOT_PINNED) # Unpinning message database.update_message_by_id(message_id, {"is_pinned": False}) return {}
def message_edit(token, message_id, message): """Given a message, update it's text with new text""" # Validate token if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) # If the message is empty, perform deletion instead if message == "": return message_remove(token, message_id) if not validator.is_valid_message(message): raise ValueError(INVALID_MESSAGE) # Convert token to u_id u_id = jwt_handler.decode_token(token) user = database.get_user_by_id(u_id) message_dict = database.get_message_by_id(message_id) if message_dict is None: raise ValueError(MESSAGE_EDIT_NOT_EXIST) channel_id = message_dict["channel_id"] channel = database.get_channel_by_id(channel_id) # Check if user can edit this message if u_id == message_dict["u_id"] or user["permission"] in [OWNER, ADMIN] \ or u_id in channel["owner_ids"]: database.update_message_by_id(message_id, {"message": message}) return {} raise AccessError(MESSAGE_EDIT_NO_AUTH)
def message_pin(token, message_id): """ Given a message within a channel, mark it as "pinned" to be given special display treatment by the frontend """ # Validate token if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) # Decode token u_id = jwt_handler.decode_token(token) user = database.get_user_by_id(u_id) message = database.get_message_by_id(message_id) if message is None: raise ValueError(MESSAGE_PIN_NOT_EXIST) channel = database.get_channel_by_id(message["channel_id"]) if user["permission"] not in [OWNER, ADMIN] \ and u_id not in channel["owner_ids"]: raise ValueError(MESSAGE_PIN_NO_AUTH) # Checking data if u_id not in channel["auth_ids"]: raise AccessError(CHANNEL_CANT_VIEW_DETAIL) if message["is_pinned"] is True: raise ValueError(MESSAGE_ALREADY_PINNED) # Pinning message database.update_message_by_id(message_id, {"is_pinned": True}) return {}
def channel_removeowner(token, channel_id, u_id): """Remove user with user id u_id an owner of this channel""" # Convert channel_id and u_id to integer channel_id = int(channel_id) u_id = int(u_id) # Validate token, channel and user if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) if not validator.is_valid_channel(channel_id): raise ValueError(INVALID_CHANNEL) if not validator.is_valid_user(u_id): raise ValueError(INVALID_USER) # Locate channel and user in database channel = database.get_channel_by_id(channel_id) auth_user_id = jwt_handler.decode_token(token) auth_user = database.get_user_by_id(auth_user_id) owner_list = channel["owner_ids"] if auth_user["permission"] not in [OWNER, ADMIN] or\ auth_user_id not in channel["owner_ids"]: raise AccessError(CHANNEL_DEL_OWNER_NO_AUTH) # Check that the added_user is currently an owner if u_id not in owner_list: raise ValueError(CHANNEL_NOT_OWNER) # Remove user from owner_ids owner_list.remove(u_id) database.update_channel_by_id(channel_id, { "owner_ids": owner_list }) return {}
def message_remove(token, message_id): """ Given a message_id for a message, this message is removed from the chxnel """ # Validate token if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) if not isinstance(message_id, int): message_id = int(message_id) # Convert token to u_id u_id = jwt_handler.decode_token(token) # Check u_id is authorised user = database.get_user_by_id(u_id) message = database.get_message_by_id(message_id) if message is None: raise ValueError(MESSAGE_REMOVE_NOT_EXIST) channel_id = message["channel_id"] channel = database.get_channel_by_id(channel_id) # if sender of message if u_id == message["u_id"] or\ user["permission"] in [OWNER, ADMIN] or\ u_id in channel["owner_ids"]: # Delete message from database database.delete_message_by_id(message_id) # Delete message from channel channel["messages"].remove(message_id) database.update_channel_by_id(channel_id, channel) return {} raise AccessError(MESSAGE_EDIT_NO_AUTH)
def channel_join(token, channel_id): """Given a channel_id of a channel that the authorised user can join, adds them to that channel""" # Validate token and channel ID if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) if not validator.is_valid_channel(channel_id): raise ValueError(INVALID_CHANNEL) # Convert token to u_id u_id = jwt_handler.decode_token(token) user = database.get_user_by_id(u_id) # Locate channel in database channel = database.get_channel_by_id(channel_id) # If channel is private if not channel["is_public"] and user["permission"] == MEMBER: # If the user is not an admin/owner raise AccessError(CHANNEL_CANT_VIEW_DETAIL) # Add user to authorised users in channel auth_list = channel["auth_ids"] if u_id not in auth_list: auth_list.append(u_id) database.update_channel_by_id(channel_id, { "auth_ids": auth_list }) else: raise ValueError(CHANNEL_ALREADY_JOINED) return {}
def channel_details(token, channel_id): """Given a Channel with ID channel_id that the authorised user is part of, provide basic details about the channel""" # Validate token and channel if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) if not validator.is_valid_channel(channel_id): raise ValueError(INVALID_CHANNEL) # Find user in database u_id = jwt_handler.decode_token(token) # Locate in database channel = database.get_channel_by_id(channel_id) user = database.get_user_by_id(u_id) # Check user is authorised if u_id not in channel["auth_ids"] and user["permission"] == MEMBER: raise AccessError(CHANNEL_CANT_VIEW_DETAIL) # Compile channel details owner_list = channel["owner_ids"] auth_list = channel["auth_ids"] owner_list_with_details = [] auth_list_with_details = [] for owner_id in owner_list: owner = database.get_user_by_id(owner_id) owner_list_with_details.append({ "u_id": owner_id, "name_first": owner["name_first"], "name_last": owner["name_last"], "profile_img_url": owner["profile_img_url"]}) for auth_id in auth_list: auth = database.get_user_by_id(auth_id) auth_list_with_details.append({ "u_id": auth_id, "name_first": auth["name_first"], "name_last": auth["name_last"], "profile_img_url": auth["profile_img_url"]}) return { "name": channel["name"], "owner_members": owner_list_with_details, "all_members": auth_list_with_details }
def is_valid_token(token): """Returns whether or not a token is valid: that the signature is valid and that it is an actively listed token under the user's data file""" u_id = jwt_handler.decode_token(token) if u_id is None: return False user = database.get_user_by_id(u_id) if user is None: return False for active_token in user["tokens"]: if active_token == token: return True return False
def auth_logout(token): """Given an active token, invalidates the taken to log the user out. If a valid token is given, and the user is successfully logged out, it returns true, otherwise false.""" # Validate data if not validator.is_valid_token(token): return {"is_success": False} # Converts token to u_id u_id = jwt_handler.decode_token(token) # Searches for the user by u_id user = database.get_user_by_id(u_id) # Searches for and removes the token from the user's active tokens token_list = user["tokens"] token_list.remove(token) database.update_user_by_id(user["u_id"], {"tokens": token_list}) return {"is_success": True}
def channel_addowner(token, channel_id, u_id): """Make user with user id u_id an owner of this channel""" # Convert channel_id and u_id to integer channel_id = int(channel_id) u_id = int(u_id) # Validate token, channel and user if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) if not validator.is_valid_channel(channel_id): raise ValueError(INVALID_CHANNEL) if not validator.is_valid_user(u_id): raise ValueError(INVALID_USER) # Locate channel and user in database channel = database.get_channel_by_id(channel_id) auth_user_id = jwt_handler.decode_token(token) auth_user = database.get_user_by_id(auth_user_id) # Check auth_user permissions if auth_user["permission"] not in [OWNER, ADMIN] or\ auth_user_id not in channel["owner_ids"]: raise AccessError(CHANNEL_ADD_OWNER_NO_AUTH) # Add user to auth_ids auth_list = channel["auth_ids"] if u_id not in auth_list: auth_list.append(u_id) database.update_channel_by_id(channel_id, { "auth_ids": auth_list }) # Add user to owner_ids owner_list = channel["owner_ids"] if u_id in owner_list: raise ValueError(CHANNEL_ALREADY_OWNER) owner_list.append(u_id) database.update_channel_by_id(channel_id, { "owner_ids": owner_list }) return {}
def user_profile(token, u_id): """For a valid user, returns information about their email, first name, last name, and handle""" # Check valid token if not validator.is_valid_token(token): raise AccessError(INVALID_TOKEN) # Check u_id is valid if not validator.is_valid_user(u_id): raise ValueError(INVALID_USER) # Return user profile user = database.get_user_by_id(u_id) return { "email": user["email"], "name_first": user["name_first"], "name_last": user["name_last"], "handle_str": user["handle"], "profile_img_url": user["profile_img_url"] }
def auth_register(email, password, name_first, name_last): """Given a user's first and last name, email address, and password, create a new account for them and return a new token for authentication in their session. A handle is generated that is the concatentation of a lowercase-only first name and last name. If the concatenation is longer than 20 characters, it is cutoff at 20 characters. If the handle is already taken, you may modify the handle in any way you see fit to make it unique.""" # Validate data if not validator.is_valid_name(name_first): raise ValueError(INVALID_NAME_FIRST) if not validator.is_valid_name(name_last): raise ValueError(INVALID_NAME_LAST) if not validator.is_valid_email(email): raise ValueError(INVALID_EMAIL) if not validator.is_unique_email(email): raise ValueError(NOT_UNIQUE_EMAIL) if not validator.is_valid_password(password): raise ValueError(INVALID_PASS) # Set permission to MEMBER perm = constants.MEMBER # If no members, permission is OWNER if len(database.get_all_users()) == 0: perm = constants.OWNER # user["handle"] handling if len(name_first + name_last) > 20: handle = [] temp = (name_first + name_last).lower() for x in range(0, 20): handle.append(temp[x]) handle_str = "".join(handle) else: handle_str = (name_first + name_last).lower() users = database.get_all_users() index = 0 for user in users: if user["handle"][0:len(handle_str)] == handle_str: index += 1 if index > 0: handle_str = handle_str + str(index) u_id = database.add_user({ "tokens": [], "name_first": name_first, "name_last": name_last, "handle": handle_str, "email": email, "password": password, "permission": perm, "pw_reset_code": "", "profile_img_url": "http://127.0.0.1:5001/static/default.jpg" }) token = jwt_handler.encode_u_id(u_id) user = database.get_user_by_id(u_id) token_list = user["tokens"] token_list.append(token) database.update_user_by_id(u_id, {"tokens": token_list}) return {"token": token}
def is_valid_user(u_id): """Returns whether or not a user id id valid""" if database.get_user_by_id(u_id) is None: return False return True