def admin_userpermission_change(token, u_id, permission_id): fl = 1 u_id = int(u_id) permission_id = int(permission_id) data = load() userDict = data['userDict'] for user in userDict: if u_id == user['u_id']: fl = 0 if fl == 1: raise ValueError('Wrong user id') if permission_id not in range(1, 4): raise ValueError('Unmatch permission id') opid = getUserFromToken(token) for user in userDict: if user['u_id'] == opid: if user['permission_id'] == 2 and permission_id == 1: raise AccessError( 'Permission Denied: Trying to give owner by admin') if user['permission_id'] == 3: raise AccessError('Permission Denied : member can not do this') for sb in userDict: if sb['u_id'] == u_id: if sb['permission_id'] == 1: raise AccessError( 'Permission Denied: Trying to change owner permission') sb['permission_id'] = permission_id data['userDict'] = userDict save(data) pass
def channel_addowner(token, channel_id, u_id): DATA = load() channelDict = DATA['channelDict'] if channel_id_check(channel_id) == False: raise ValueError("channel_id is invalid") # already an owner getUserFromToken(token) u_id = int(u_id) channel_id = int(channel_id) for parts in channelDict: if parts['channel_id'] == channel_id and u_id in parts['channel_owner']: raise ValueError("user is already an owner in the channel") if not if_User_Owner(token, channel_id): raise AccessError( "the authorised user is not an owner of the slackr, or an owner of this channel" ) if u_id not in channelDict[channel_id - 1]['channel_member']: raise AccessError("the user is not a member of this channel") for parts in channelDict: if parts['channel_id'] == channel_id: parts['channel_owner'].append(u_id) parts['channel_member'].remove(u_id) DATA['channelDict'] = channelDict save(DATA) return {}
def standup_send(token, channel_id, message): channel_id = int(channel_id) data = load() channelDict = data['channelDict'] userDict = data['userDict'] opid = getUserFromToken(token) for user in userDict: if int(user['u_id']) == int(opid): name = user['first_name'] break if len(message) > 1000: raise ValueError("Message too long") for ch in channelDict: if int(channel_id) == int(ch['channel_id']): if opid not in ch['channel_member'] and opid not in ch[ 'channel_owner']: raise AccessError('You are not a member of this channel') if ch['standUp'] != True: raise ValueError( 'An active standup is not currently running in this channel' ) append = str(name) + ': ' + str(message) if not ch['standlist']: ch['standlist'] = append data['channelDict'] = channelDict save(data) return {} else: ch['standlist'] += '\r\n' + append data['channelDict'] = channelDict save(data) return {} raise ValueError('Channel ID is not a valid channel')
def message_send(token, channel_id, message): u_id = getUserFromToken(token) DATA = load() messDict = DATA['messDict'] channelDict = DATA['channelDict'] if len(message) > 1000: raise ValueError("Message is more than 1000 characters") for cha in channelDict: if cha['channel_id'] == channel_id: if u_id not in cha['channel_owner'] and u_id not in cha[ 'channel_member']: raise AccessError( "The authorised user has not joined the channel they are trying to post to" ) DATA['messID'] += 1 mess = { 'channel_id': int(channel_id), 'message_id': int(DATA['messID']), 'u_id': int(u_id), 'message': message, 'time_created': int(datetime.now().timestamp()), 'reacts': [{ 'react_id': None, 'u_ids': [], 'is_this_user_reacted': False }], 'is_pinned': False } mess_id = int(mess['message_id']) messDict.append(mess) DATA['messDict'] = messDict save(DATA) return int(mess_id)
def channel_join(token, channel_id): DATA = load() channelDict = DATA['channelDict'] if channel_id_check(channel_id) == False: raise ValueError("channel_id is invalid") id = getUserFromToken(token) id = int(id) # private channel if channel_property_check(channel_id) == False: if channel_admin_check(token) == False: raise AccessError( "authorised user is not an admin when channel is private") else: for parts in channelDict: if parts['channel_id'] == int(channel_id): parts['channel_owner'].append(id) # public channel else: for parts in channelDict: if parts['channel_id'] == int(channel_id): if channel_admin_check(token) == False: if parts['channel_member'] == []: parts['channel_member'] = [id] else: parts['channel_member'].append(id) else: parts['channel_owner'].append(id) DATA['channelDict'] = channelDict save(DATA)
def start_standup(token, channel_id, length): ''' Start a standup Length is in seconds ''' data = get_data() channel = get_channel(data, channel_id) user = get_user_from_token(data, token) # If the channel is Invalid if channel == None: raise ValueError(description='Invalid Channel') # If the channel is alreay in stadup mode if is_standup_active(channel): raise ValueError(description='Standup is already active') # If the user is not in this channel if not user_in_channel(user['u_id'], channel): raise AccessError(description='User is not in channel') # Else start a start up session channel['standup_active'] = True # setup the timer for with the length specified timer = threading.Timer(length, stop_standup, [token, channel_id]) time_finish = (datetime.now() + timedelta(seconds=length)).timestamp() channel['standup_finish'] = time_finish pickle_data(data) timer.start() return {'time_finish': time_finish}
def get_messages(token, channel_id, start): ''' given a token, channel_id and the start, show all th emessages in channel with channel_id after the start as long as the user with token is part of the channel ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) if channel is None: raise ValueError('Channel does not exist') num_messages = len(channel['message_ids']) if start > num_messages: raise ValueError('Start is greater than the total number of messages') if not user_in_channel(user['u_id'], channel): raise AccessError('User is not in channel') end = start + 50 if end > num_messages: end = -1 messages = return_messages(data, channel['message_ids'][start:], token) else: messages = return_messages(data, channel['message_ids'][start:end], token) return {'messages': messages, 'start': start, 'end': end}
def channel_addowner(token, channel_id, u_id): ''' make an user an owner of the channel ''' channel = get_channel_by_channel_id(channel_id) # channel_id does not refer to a valid channel if channel is None: raise ValueError("Channel does not exist") # user is already an owner of the channel if channel.is_owner(u_id): raise ValueError("User is already an owner of the channel") # User does not have permission to add owner if not channel.is_owner(decode_token(token)) and \ not token_is_admin(token) and \ not token_is_owner(token): raise AccessError("User is not an owner of the channel or slackrowner") # User is added as owner channel.add_owner(u_id) return {}
def message_edit(token, message_id, message): ''' Given a message, update it's text with new text. If the new message is an empty string, the message is deleted. ''' channel = get_channel_by_message_id(message_id) message_obj = get_message_by_message_id(message_id) user = get_user_by_token(token) # message_id does not refer to an existing message if not valid_message_id(message_id): raise ValueError("Message does not exist") # message is not of appropriate length if valid_message(message): raise ValueError("Message length too long") # User does not have permission to edit message if not message_obj.user_sent_message(user.u_id) and \ not token_is_admin(token) and \ not token_is_owner(token) and \ not channel.is_owner(user.u_id): raise AccessError("User does not have permission") # Edit channel message if not message.strip(): # If empty message, delete channel = get_channel_by_message_id(message_id) channel.remove_message(message_id) else: # Otherwise, edit message message_obj.edit_message(message) return {}
def message_unpin(token, message_id): ''' Given a message within a channel, remove it's mark as unpinned ''' channel = get_channel_by_message_id(message_id) message_obj = get_message_by_message_id(message_id) user = get_user_by_token(token) # Message_id does not refer to an existing message if not valid_message_id(message_id): raise ValueError("Message does not exist") # Message_id is already unpinned if not message_obj.is_pinned: raise ValueError("Message is currently unpinned") # User is not a member of the channel if not channel.is_member(user.u_id): raise AccessError("Authorised user is not a member of the channel") # User is not an owner of the channel if not channel.is_owner(user.u_id) and \ not token_is_admin(token) and \ not token_is_owner(token): raise ValueError("User is not an admin") # Unpinning message message_obj.unpin_message() return {}
def message_send(token, channel_id, message): ''' Send a message from authorised_user to the channel specified by channel_id ''' channel = get_channel_by_channel_id(channel_id) user = get_user_by_token(token) # Channel_id does not refer to a valid channel if channel is None: raise ValueError("Invalid Channel ID") # Message is not of appropriate length if valid_message(message): raise ValueError("Message length too long") # User has not joined the channel if not channel.is_member(user.u_id): raise AccessError("Authorised user is not a member of the channel") message_object = global_var.Message(user.u_id, message, channel_id) # Append message to channel list channel.add_message(message_object) return { "message_id": message_object.id }
def message_unreact(token, message_id, react_id): ''' Given a message within a channel the authorised user is part of, remove a "react" to that particular message ''' channel = get_channel_by_message_id(message_id) message_obj = get_message_by_message_id(message_id) user = get_user_by_token(token) # Message_id does not refer to an existing message if not valid_message_id(message_id): raise ValueError("Message does not exist") # User is not a member of the channel if not channel.is_member(user.u_id): raise AccessError("Authorised user is not a member of the channel") # React_id does not refer to a valid react if not valid_react_id(react_id): raise ValueError("Invalid React ID") # Message already has an react id by the given user if not message_obj.user_has_reacted(user.u_id, react_id): raise ValueError("Message does not contain an active react") # Removing react from message message_obj.remove_react(user.u_id, react_id) return {}
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 ''' channel = get_channel_by_message_id(message_id) message_obj = get_message_by_message_id(message_id) user = get_user_by_token(token) # Message_id does not refer to an existing message if not valid_message_id(message_id): raise ValueError("Message does not exist") # Message_id is already pinned if message_obj.is_pinned: raise ValueError("Message is currently pinned") # User is not a member of the channel if not channel.is_member(user.u_id): raise AccessError("Authorised user is not a member of the channel") # User is not an owner of the channel if not channel.is_owner(user.u_id) and \ not token_is_admin(token) and \ not token_is_owner(token): raise ValueError("User is not an admin") # Pin message message_obj.pin_message() return {}
def message_pin(token, message_id): u_id = getUserFromToken(token) u_id = int(u_id) message_id = int(message_id) DATA = load() messDict = DATA['messDict'] found = False for mess in messDict: if mess['message_id'] == message_id: if mess['is_pinned']: raise ValueError('already pinned') channelID = mess['channel_id'] message = mess found = True break if not found: raise ValueError("Invalid message_id") if not if_User_Owner(token, channelID): raise ValueError('The authorised user is not an admin') if not is_in_channel(u_id, channelID): raise AccessError( 'message_id is not a valid message within a channel that the authorised user has joined' ) message['is_pinned'] = True DATA['messDict'] = messDict save(DATA) return {}
def message_sendlater(token, channel_id, message, time_sent): ''' Sends a message from authorised_user to the channel specified by channel_id automatically at a specified time in the future ''' channel = get_channel_by_channel_id(channel_id) user = get_user_by_token(token) # Channel_id does not refer to a valid channel if channel is None: raise ValueError("Invalid Channel ID") # Message is not of appropriate length if valid_message(message): raise ValueError("Message length too long") # Time to be sent is in the past if time_sent < datetime.datetime.now().timestamp(): raise ValueError("Time sent was in the past") # User has not joined the channel if not channel.is_member(user.u_id): raise AccessError("Authorised user is not a member of the channel") # create new message object and update send time message_object = global_var.Message(user.u_id, message, channel_id) message_object.time_created = time_sent time_diff = time_sent - datetime.datetime.now().timestamp() Timer(time_diff, channel.add_message, args=[message_object]).start() return { "message_id": message_object.id }
def send_message(token, channel_id, message_str): """ Send a message to the channel associated with channel_id """ data = get_data() channel = get_channel(data, channel_id) user = get_user_from_token(data, token) message_id = get_next_message_id(data) if not valid_message_len(message_str): raise ValueError("Message too long") if not user_in_channel(user['u_id'], channel): raise AccessError("User is not in channel") # get the current time in utc now = datetime.utcnow().replace(tzinfo=timezone.utc).timestamp() # set up the information to save in the 'database' message_info = generate_message_info(channel_id, message_id, user['u_id'], message_str, now) # insert the message into the front of the message ids # stored in the channel channel['message_ids'].insert(0, message_id) # add the message object to the messages list data['messages'].append(message_info) pickle_data(data) return {'message_id': message_id}
def channels_messages(token, channel_id, start): u_id = getUserFromToken(token) u_id = int(u_id) DATA = load() messDict = DATA['messDict'] start = int(start) if channel_id_check(channel_id) == False: raise ValueError("channel_id is invalid") if auth_id_check(token, channel_id) == False: raise AccessError("Auth user is not a member of channnel") dic = {'messages': [], 'start': start, 'end': None} lis = [] for parts in messDict: if int(parts['channel_id']) == int(channel_id): lis.append(int(parts['message_id'])) if len(lis) != 1: lis = lis[::-1] lis = get_messages(u_id, lis) if len(lis) < int(start): raise ValueError( "start is greater than the total number of messages in the channel" ) if int(start) + 50 >= len(lis): for parts in lis[int(start):len(lis)]: dic['messages'].append(parts) dic['end'] = -1 else: for parts in lis[int(start):int(start) + 50]: dic['messages'].append(parts) dic['end'] = start + 50 return dic
def standup_start(token, channel_id, length): ''' For a given channel, start the standup period whereby for the next "length" seconds if someone calls "standup_send" with a message, it is buffered during the X second window then at the end of the X second window a message will be added to the message queue in the channel from the user who started the standup. X is an integer that denotes the number of seconds that the standup occurs for ''' channel = get_channel_by_channel_id(channel_id) user = get_user_by_token(token) if channel is None: raise ValueError("Channel Does Not Exist") if channel.standup_running() is not False: raise ValueError("Standup Already Running") if not channel.is_member(user.u_id): raise AccessError("Cannot Access Channel") # Start standup and after length seconds end the standup time = datetime.datetime.now() + datetime.timedelta(seconds=length) channel.start_standup(time.timestamp()) Timer(length, channel.end_standup, args=[token]).start() return {"time_finish" : time.timestamp()}
def channel_messages(token, channel_id, start): ''' Returns up to 50 messages between index "start" and "start + 50". Message with 0 index is the most recent message end = start + 50 If function has returned the least recent messages in the channel returns -1 in "end" to indicate there are no more msgs to load ''' channel = get_channel_by_channel_id(channel_id) u_id = decode_token(token) # channel_id does not refer to a valid channel if channel is None: raise ValueError("Channel does not exist") # user is not a member of the channel if not channel.is_member(u_id): raise AccessError("Authorised user is not a member of the channel") # If the start is greater than the number of messages in the channel given if start > len(channel.messages): raise ValueError("Start index is invalid") messages = [] for i in range(MAX_MESSAGES): # End index of -1 to indicate there are no more messages to load if start + i >= len(channel.messages): return {"messages": messages, "start": start, "end": -1} # Gets message object message = channel.messages[start + i] # Add information regarding if user has reacted to this message reacts = message.reacts for react in reacts: react["is_this_user_reacted"] = \ message.user_has_reacted(u_id, react['react_id']) # Append message dictionary into messages list messages.append({ "message_id": message.id, "u_id": message.sender, "message": message.message, "time_created": message.time_created, "reacts": reacts, "is_pinned": message.is_pinned, }) # Check which if start + MAX_MESSAGES >= len(channel.messages): end = -1 else: end = start + MAX_MESSAGES return {"messages": messages, "start": start, "end": end}
def getUserFromToken(token): global SECRET try: decoded = jwt.decode(token[2:len(token) - 1], SECRET, algorithms=['HS256']) u_id = decoded['u_id'] return u_id except: raise AccessError('Invalid token')
def channel_invite(token, channel_id, u_id): if channel_id_check(int(channel_id)) == False: raise ValueError("channel_id is invalid") if u_id_check(u_id) == False: raise ValueError("u_id does not refer to a valid user") if auth_id_check(token, channel_id) == False: raise AccessError("Auth user is not a member of channel") if is_in_channel(u_id, channel_id): raise AccessError('The user you are inviting is already in this channel.') DATA = load() channelDict = DATA['channelDict'] for parts in channelDict: if int(parts['channel_id']) == int(channel_id): # the user invite by owner is also a owner if if_slackr_owner(token) == True: parts['channel_owner'].append(int(u_id)) else: parts['channel_member'].append(int(u_id)) DATA['channelDict'] = channelDict save(DATA) return {}
def channel_details(token, channel_id): DATA = load() channelDict = DATA['channelDict'] if channel_id_check(channel_id) == False: raise ValueError("channel_id is invalid") if not auth_id_check(token, channel_id): raise AccessError("Auth user is not a member of channel") detail = {} for parts in channelDict: if int(parts['channel_id']) == int(channel_id): all_members = list(parts['channel_member']) + list(parts['channel_owner']) detail['name'] = parts['name'] detail['all_members'] = list(get_members(all_members)) detail['owner_members'] = list(get_members(list(parts['channel_owner']))) return dict(detail)
def join_channel(token, channel_id): ''' given a user's token and a channel_id, the user can join the channel as long as the channel is private or the user has permissions such as being an admin or owner of slackr ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) #print(user_in_channel(user['email'], channel)) if channel is None or user_in_channel(user['u_id'], channel): raise ValueError('invalid channel id') if user['perm_id'] == MEMBER_ID and not channel['is_public']: raise AccessError('User is not an admin or owner of slackr') user_info = generate_user_info(user) channel['members'].append(user_info) pickle_data(data) return {}
def details_channel(token, channel_id): ''' given a token of a user and a channel_id, show the owners and members of the channel with channel_id as long as the user is a member of the channel ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) if channel is None: raise ValueError('invalid channel id') if not user_in_channel(user['u_id'], channel): raise AccessError('user not part of channel') pickle_data(data) return { 'name': channel['name'], 'owner_members': get_members(channel['owners']), 'all_members': get_members(channel['members']) }
def edit_message(token, message_id, message_str): """ Edit message with message_id with new message If message is empty, delete the message """ if len(message_str) == 0: return remove_message(token, message_id) data = get_data() og_message = get_msg_from_msg_id(data, message_id) user = get_user_from_token(data, token) channel = get_channel(data, og_message['channel_id']) # check if user did not send original message and user is admin/owner if (not user_sent_message(user['u_id'], og_message) and not user_is_admin_or_owner(user, channel)): raise AccessError("User did not send message or not enough privileges") # edit the original message with the new message og_message['message'] = message_str pickle_data(data) return {}
def message_remove(token, message_id): DATA = load() messDict = DATA['messDict'] found = False for mess in messDict: if mess['message_id'] == int(message_id): channelID = int(mess['channel_id']) message = mess found = True break if not found: raise ValueError("Message (based on ID) no longer exists") if not is_owner(token, channelID) and not is_sender(token, message_id): raise AccessError('Unauthorised remove !') messDict.remove(message) DATA['messDict'] = messDict save(DATA) return {}
def remove_message(token, message_id): """ Remove message with message_id from channel """ data = get_data() user = get_user_from_token(data, token) message = get_msg_from_msg_id(data, message_id) if message is None: raise ValueError('Message no longer exists') channel = get_channel(data, message['channel_id']) if not user_sent_message(user['u_id'], message) and not user_is_admin_or_owner( user, channel): raise AccessError("User did not send message or not enough privileges") # remove the message object and the message_id from the 'database' data['messages'].remove(message) channel['message_ids'].remove(message_id) pickle_data(data) return {}
def standup_send(token, channel_id, message): ''' Sending a message to get buffered in the standup queue, assuming a standup is currently active ''' channel = get_channel_by_channel_id(channel_id) user = get_user_by_token(token) if channel is None: raise ValueError("Channel Does Not Exist") if len(message) > MAX_MESSAGE_LENGTH: raise ValueError("Message Too Long") if not channel.is_member(user.u_id): raise AccessError("Cannot Access Channel") if channel.standup_running() is False: raise ValueError("Not Currently In Standup") channel.add_standup_message(token, message) return {}
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 ''' # Getting user object user = get_user_by_u_id(u_id) # Checking validity of permission change request if not user: raise ValueError('Invalid User ID') if not valid_permission_id(permission_id): raise ValueError('Permission ID is invalid') if not (token_is_admin(token) or token_is_owner(token)): raise AccessError('Current user is not an admin or owner') # Changing user's permission user.change_permissions(permission_id) return {}
def unpin_message(token, message_id): """ Unpin message with message_id """ data = get_data() user = get_user_from_token(data, token) message = get_msg_from_msg_id(data, message_id) if message is None: raise ValueError("Invalid message_id") channel = get_channel(data, message['channel_id']) if not perm_id_is_admin_owner(user['perm_id']): raise ValueError("User is not an admin or owner") if not message['is_pinned']: raise ValueError("Message is not pinned") if not user_in_channel(user['u_id'], channel): raise AccessError( "User not part of channel that the message is within") # set the pin flag on the message to False message['is_pinned'] = False pickle_data(data) return {}