def user_profiles_uploadphoto(token, img_url, x_start, y_start, x_end, y_end): if img_url[-4:] != '.jpg' and img_url[-5:] != '.jpeg': raise ValueError(f"Invalid url: '{img_url}'") identifier = str(uuid.uuid4()) PROFILE_IMG_URL = unbox('url_base', '') + '/user/profiles/photo/' + identifier + '.jpg' FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../utility/storage/' + identifier + '.jpg') try: urllib.request.urlretrieve(img_url, FILE) except Exception: raise ValueError(f"Cannot retrieve image: '{img_url}'") try: img = Image.open(FILE) cropped = img.crop((x_start, y_start, x_end, y_end)) cropped.save(FILE) except Exception: os.remove(FILE) raise ValueError("Cannot crop image") users = unbox('users', []) users[str(decode(token)['u_id'])]['profile_img_url'] = PROFILE_IMG_URL box('users', users) return {}
def message_unreact(token, message_id, react_id): users = unbox('users', {}) channels = unbox('channels', {}) messages = unbox('messages', {}) auth = users[str(decode(token)['u_id'])] message = messages[str(message_id)] channel = channels[str(message['channel_id'])] if auth['u_id'] not in channel['all_members']: raise AccessError("Unauthorised") if react_id not in [1]: raise ValueError(f"Invalid ID: react_id - {react_id}") reacts = messages[str(message_id)]['reacts'] if str(react_id) not in reacts or auth['u_id'] not in reacts[str(react_id)]['u_ids']: raise ValueError("React doesn't exist") messages[str(message_id)]['reacts'][str(react_id)]['u_ids'].remove(auth['u_id']) box('messages', messages) return {}
def message_react(token, message_id, react_id): users = unbox('users', {}) channels = unbox('channels', {}) messages = unbox('messages', {}) auth = users[str(decode(token)['u_id'])] message = messages[str(message_id)] channel = channels[str(message['channel_id'])] if auth['u_id'] not in channel['all_members']: raise AccessError("Unauthorised") if react_id not in [1]: raise ValueError(f"Invalid ID: react_id - {react_id}") reacts = message['reacts'] if str(react_id) in reacts and auth['u_id'] in reacts[str( react_id)]['u_ids']: raise ValueError("React already exists") if str(react_id) in reacts: reacts[str(react_id)]['u_ids'].append(auth['u_id']) else: reacts[str(react_id)] = {'react_id': react_id, 'u_ids': [auth['u_id']]} message['reacts'] = reacts messages[str(message_id)] = message box('messages', messages) return {}
def auth_register(email, password, name_first, name_last): email_to_u_id = unbox('email_to_u_id', {}) handle_to_u_id = unbox('handle_to_u_id', {}) users = unbox('users', {}) if not re.search('^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$', email): raise ValueError(f"Invalid email: '{email}'") if email in email_to_u_id: raise ValueError("Email already in use") if len(password) < 6: raise ValueError("Invalid password") if not (1 < len(name_first) < 50): raise ValueError("First name too short") if not (1 < len(name_last) < 50): raise ValueError("Last name too short") handle_str = name_first.lower() + name_last.lower() if len(handle_str) > 20: handle_str = handle_str[0:20] if handle_str in handle_to_u_id: handle_str = handle_str + str(len(handle_to_u_id)) u_id = 0 if not users else max([int(id) for id in users]) + 1 handle_to_u_id[handle_str] = u_id email_to_u_id[email] = u_id profile_img_url = unbox('url_base', '') + '/user/profiles/photo/default.jpg' users[str(u_id)] = { 'u_id': u_id, 'email': email, 'password': hashlib.sha256(password.encode()).hexdigest(), 'permission_id': 1 if u_id == 0 else 3, 'profile_img_url': profile_img_url, 'name_first': name_first, 'name_last': name_last, 'handle_str': handle_str } box('handle_to_u_id', handle_to_u_id) box('email_to_u_id', email_to_u_id) box('users', users) return auth_login.auth_login(email, password)
def channels_create(token, name, is_public): users = unbox('users', {}) channels = unbox('channels', {}) auth = users[str(decode(token)['u_id'])] if auth['permission_id'] == 3: raise AccessError("Unauthorised") if len(name) > 20: raise ValueError("Invalid name (too long)") channel_id = 0 if len(channels) == 0 else max([int(id) for id in channels]) + 1 channels[str(channel_id)] = { 'channel_id': channel_id, 'name': name, 'is_public': is_public, 'all_members': [auth['u_id']], 'owner_members': [auth['u_id']] } box('channels', channels) return {'channel_id': channel_id}
def message_send(token, channel_id, message): users = unbox('users', {}) channels = unbox('channels', {}) messages = unbox('messages', {}) auth = users[str(decode(token)['u_id'])] channel = channels[str(channel_id)] if auth['u_id'] not in channel['all_members']: raise AccessError("Unauthorised") if not (1 <= len(message) <= 1000): raise ValueError("Message is either too long or too short") message_id = 0 if len(messages) == 0 else max([int(id) for id in messages]) + 1 messages[str(message_id)] = { 'message_id': message_id, 'channel_id': channel_id, 'u_id': auth['u_id'], 'message': message, 'time_created': int(time.time()), 'reacts': {}, 'is_pinned': False } box('messages', messages) return {'message_id': message_id}
def user_profile_setname(token, name_first, name_last): if not (1 < len(name_first) < 50): raise ValueError("First name too short") if not (1 < len(name_last) < 50): raise ValueError("Last name too short") users = unbox('users', {}) auth = users[str(decode(token)['u_id'])] auth['name_first'] = name_first auth['name_last'] = name_last users[str(auth['u_id'])] = auth box('users', users) return {}
def auth_passwordreset_reset(reset_code, new_password): users = unbox('users', {}) reset_code_to_u_id = unbox('reset_code_to_u_id', {}) if reset_code not in reset_code_to_u_id: raise ValueError(f"Invalid reset code: '{reset_code}'") if len(new_password) < 6: raise ValueError("Invalid new password") user = users[str(reset_code_to_u_id[reset_code])] del reset_code_to_u_id[reset_code] user['password'] = hashlib.sha256(new_password.encode()).hexdigest() users[user['u_id']] = user box('reset_code_to_u_id', reset_code_to_u_id) box('users', users) return {}
def standup_send(token, channel_id, message): users = unbox('users', {}) channels = unbox('channels', {}) channel_id_to_time_finish = unbox('channel_id_to_time_finish', {}) channel_id_to_messages = unbox('channel_id_to_messages', {}) auth = users[str(decode(token)['u_id'])] channel = channels[str(channel_id)] if str(channel_id) not in channel_id_to_time_finish: raise ValueError("No standup has been started") if auth['u_id'] not in channel['all_members']: raise AccessError("Unauthorised") if not (1 <= len(message) <= 1000): raise ValueError("Message too long or too short") channel_id_to_messages[str(channel_id)].append({'u_id': auth['u_id'], 'message': message}) box('channel_id_to_messages', channel_id_to_messages) return {}
def user_profile_sethandle(token, handle_str): handle_to_u_id = unbox('handle_to_u_id', {}) users = unbox('users', {}) if not (3 <= len(handle_str) <= 20): raise ValueError("Handle too long or too short") if handle_str in handle_to_u_id: raise ValueError("Handle already in use") auth = users[str(decode(token)['u_id'])] del handle_to_u_id[auth['handle_str']] auth['handle_str'] = handle_str handle_to_u_id[handle_str] = auth['u_id'] users[str(auth['u_id'])] = auth box('handle_to_u_id', handle_to_u_id) box('users', users) return {}
def message_sendlater(token, channel_id, message, time_sent): users = unbox('users', {}) channels = unbox('channels', {}) messages = unbox('messages', {}) auth = users[str(decode(token)['u_id'])] channel = channels[str(channel_id)] if auth['u_id'] not in channel['all_members']: raise AccessError("Unauthorised") if not (1 <= len(message) <= 1000): raise ValueError("Message is either too long or too short") nowish = int(time.time()) if time_sent < nowish: raise ValueError("Time to send is in the past") message_id = 0 if len(messages) == 0 else max([int(id) for id in messages]) + 1 messages[str(message_id)] = { 'message_id': message_id, 'channel_id': None, 'u_id': None, 'message': message, 'time_created': time_sent, 'reacts': {}, 'is_pinned': False } box('messages', messages) timer = Timer(time_sent - nowish, _delayed, args=[auth['u_id'], message_id, channel_id], kwargs=None) timer.start() return { 'message_id': message_id }
def user_profile_setemail(token, email): email_to_u_id = unbox('email_to_u_id', {}) users = unbox('users', {}) auth = users[str(decode(token)['u_id'])] if not re.search('^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$', email): raise ValueError(f"Invalid email: {email}") if email in email_to_u_id: raise ValueError("Email already in use") del email_to_u_id[auth['email']] auth['email'] = email email_to_u_id[email] = auth['u_id'] # update users users[str(auth['u_id'])] = auth box('email_to_u_id', email_to_u_id) box('users', users) return {}
def auth_login(email, password): email_to_u_id = unbox('email_to_u_id', {}) users = unbox('users', {}) if not re.search('^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$', email): raise ValueError(f"Invalid email: '{email}'") if email not in email_to_u_id: raise ValueError(f"Invalid email: '{email}'") user = users[str(email_to_u_id[email])] if hashlib.sha256(password.encode()).hexdigest() != user['password']: raise ValueError(f"Invalid credentials") token = encode({'u_id': user['u_id'], 'timestamp': int(round(time.time()))}) tokens = unbox('tokens', []) tokens.append(token) box('tokens', tokens) return { 'u_id' : user['u_id'], 'token' : token }
def channel_messages(token, channel_id, start): users = unbox('users', {}) channels = unbox('channels', {}) messages = unbox('messages', {}) auth = users[str(decode(token)['u_id'])] channel = channels[str(channel_id)] if auth['u_id'] not in channel['all_members']: raise AccessError("Unauthorised") messages = [{ 'message_id': m['message_id'], 'u_id': m['u_id'], 'time_created': m['time_created'], 'reacts': [{ 'react_id': r['react_id'], 'u_ids': r['u_ids'], 'is_this_user_reacted': (auth['u_id'] in r['u_ids']) } for r in m['reacts'].values()], 'is_pinned': m['is_pinned'], 'message': m['message'] } for m in sorted( [m for m in messages.values() if m['channel_id'] == channel_id], key=lambda k: k['time_created'])] count = len(messages) if start > count: raise ValueError("Requesting out of range messages") end = -1 if count - start < 50 else start + 50 return { 'messages': messages[start:] if end == -1 else messages[start:end - 1], 'start': start, 'end': end }
def auth_passwordreset_request(email): email_to_u_id = unbox('email_to_u_id', {}) reset_code_to_u_id = unbox('reset_code_to_u_id', {}) if email not in email_to_u_id: raise ValueError(f"Invalid Email: '{email}'") reset_code = hashlib.sha256( (email + str(int(time.time()))).encode()).hexdigest()[:8] reset_code_to_u_id[reset_code] = email_to_u_id[email] box('reset_code_to_u_id', reset_code_to_u_id) mail( email, "Slackr: Password Reset", f"Please enter the following code to reset your password: {reset_code}" ) return {}
def channel_join(token, channel_id): users = unbox('users', {}) channels = unbox('channels', {}) auth = users[str(decode(token)['u_id'])] channel = channels[str(channel_id)] if auth['u_id'] in channel['all_members']: raise ValueError("Already a member") if auth['permission_id'] == 3 and not channel['is_public']: raise AccessError("Unauthorised") channel['all_members'].append(auth['u_id']) channels[str(channel_id)] = channel box('channels', channels) return {}
def message_unpin(token, message_id): users = unbox('users', {}) channels = unbox('channels', {}) messages = unbox('messages', {}) auth = users[str(decode(token)['u_id'])] message = messages[str(message_id)] channel = channels[str(message['channel_id'])] if not message['is_pinned']: raise ValueError("Message is not pinned") if auth['permission_id'] == 3 and auth['u_id'] not in channel[ 'owner_members']: raise AccessError("Unauthorised") message['is_pinned'] = False messages[str(message_id)] = message box('messages', messages) return {}
def standup_start(token, channel_id, length): users = unbox('users', {}) channels = unbox('channels', {}) channel_id_to_time_finish = unbox('channel_id_to_time_finish', {}) channel_id_to_messages = unbox('channel_id_to_messages', {}) auth = users[str(decode(token)['u_id'])] channel = channels[str(channel_id)] if str(channel_id) in channel_id_to_time_finish: raise ValueError("Standup already started") time_finish = int(time.time()) + length channel_id_to_time_finish[str(channel_id)] = time_finish channel_id_to_messages[str(channel_id)] = [] box('channel_id_to_messages', channel_id_to_messages) box('channel_id_to_time_finish', channel_id_to_time_finish) timer = Timer(length, _delay, args=[token, channel_id], kwargs=None) timer.start() return {'time_finish': time_finish}
def channel_invite(token, channel_id, u_id): users = unbox('users', {}) channels = unbox('channels', {}) auth = users[str(decode(token)['u_id'])] user = users[str(u_id)] channel = channels[str(channel_id)] if user['u_id'] in channel['all_members']: raise ValueError("User already member") if auth['permission_id'] == 3 and auth['u_id'] not in channel[ 'all_members']: raise AccessError("Unauthorised") channel['all_members'].append(u_id) channels[str(channel_id)] = channel box('channels', channels) return {}