示例#1
0
def invite(token, channel_id, u_id):
    '''
    Invites a user (with user id u_id) to join a channel with
    ID channel_id. Once invited the user is added to
    the channel immediately
    '''
    data = getData()
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]

    if int(u_id) >= len(data['users']):
        raise Value_Error(f"u_id: {u_id} does not refer to a valid user.")

    if not inChannel(token, channel_id):
        raise AccessError("the authorised user is not already a member of the channel.")

    invitee = data['users'][int(u_id)]
    invitee_info = user_detail(u_id, invitee['name_first'], invitee['name_last'], invitee['profile_img_url'])

    if invitee_info not in right_channel['members']:
        right_channel['members'].append(invitee_info)
        invitee['user_channel'].append(right_channel['channel'])
    save(data)
    return {}
示例#2
0
def 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 '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_dict = data['messages'][find_message(message_id)]
    reacts_list = msg_dict['reacts']
    channel_id = msg_dict['channel_id']
    '''Check if the user is in this particular channel_id of the message '''
    user_channel_list = user_dict['user_channel']
    error_flag = 1
    for i in user_channel_list:
        if i['channel_id'] == channel_id:
            error_flag = 0

    if error_flag == 1:
        raise Value_Error(
            "Not a valid message within a channel that the authorised user has joined"
        )

    if react_id != 1:
        raise Value_Error("Not a valid react_id")

    reacts_list = msg_dict['reacts']

    if user_id not in reacts_list[int(react_id) - 1]['u_ids']:
        raise Value_Error(
            "Message with ID message_id does not contain an active React with ID react_id"
        )

    reacts_list[int(react_id) - 1]['u_ids'].remove(user_id)
    save(data)
    return {}
示例#3
0
def unpin(token, message_id):
    ''' Given a message within a channel, remove it's mark as unpinned '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_id = find_message(message_id)

    if msg_id is None:
        raise Value_Error("Message_Id is not a valid message")

    msg_dict = data['messages'][msg_id]

    if user_dict['permission'] is 3:
        raise Value_Error(
            "Message with message_id was not sent by the authorised user making this request and The authorised user is not an admin or owner of this channel or the slackr"
        )

    if not inChannel(token, msg_dict['channel_id']):
        raise AccessError("you need to be in the channel to pin the message")

    if msg_dict['is_pinned'] is False:
        raise Value_Error(
            f"Message with ID message_id: {message_id} already unpinned")

    msg_dict['is_pinned'] = False
    save(data)
    return {}
示例#4
0
def pin(token, message_id):
    ''' Given a message within a channel, mark it as "pinned" to
    be given special display treatment by the frontend '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_id = find_message(message_id)

    if msg_id is None:
        raise Value_Error("Message_Id is not a valid message")

    msg_dict = data['messages'][msg_id]

    if user_dict['permission'] == 3:
        raise Value_Error("The authorised user is not an admin")

    if not inChannel(token, msg_dict['channel_id']):
        raise AccessError(
            "The authorised user is not a member of the channel that the message is within"
        )

    if msg_dict['is_pinned'] is True:
        raise Value_Error(
            f"Message with ID message_id: {message_id} already pinned")

    msg_dict['is_pinned'] = True
    save(data)
    return {}
示例#5
0
def create(token, name, is_public):
    ''' Creates a new channel with that name that is either
    a public or private channel '''
    data = getData()
    user_id = getUserFromToken(token)

    if user_id not in range(len(data['users'])):
        raise Value_Error("the token doesn't exist")

    if len(name) > 20:
        raise Value_Error("the name is longer than 20 character")

    user = data['users'][user_id]
    user_info = user_detail(user_id, user['name_first'], user['name_last'], user['profile_img_url'])

    ch_id = len(data['channels_list'])
    data['channels_list'].append({'channel': {'channel_id': ch_id, 'name': name},
                                  'owners': [user_info],
                                  'members': [user_info],
                                  'is_public': is_public,
                                  'standup': {'finish_time': dt.utcnow(), 'message_id': None}})
    user['user_channel'].append({'channel_id': ch_id, 'name': name})

    save(data)
    return {'channel_id': ch_id}
示例#6
0
def standup_send(token, channel_id, message):
    '''Sending a message to get buffered in the standup queue,
    assuming a standup is currently active'''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    right_channel_index = find_channel(channel_id)

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    right_channel = data['channels_list'][right_channel_index]

    if len(message) > 1000:
        raise Value_Error("Message is more than 1000 characters")

    if right_channel['standup']['finish_time'] < dt.utcnow():
        raise Value_Error(
            'An active standup is not currently running in this channel')

    if not inChannel(token, channel_id):
        raise AccessError(
            'The authorised user is not a member of the channel that the message is within'
        )

    message_id = right_channel['standup']['message_id']
    msg_id = find_message(message_id)
    old_message = data['messages'][msg_id]['message']
    old_message += str(user['handle']) + ': ' + message + ' '
    edit(token, message_id, old_message)

    # update data after edit
    data = getData()
    save(data)
    return {}
示例#7
0
def sendlater(token, channel_id, message, time_sent):
    ''' Send a message from authorised_user to the channel specified
    by channel_id automatically at a specified time in the future '''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    right_channel_index = find_channel(channel_id)

    if type(time_sent) != dt:
        time_sent = dt.utcfromtimestamp(int(time_sent))

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    message_id = get_new_message_id()

    if len(message) > 1000:
        raise Value_Error("Message is more than 1000 characters")

    if not inChannel(token, channel_id):
        raise AccessError(
            "the authorised user has not joined the channel they are trying to post to"
        )

    now = dt.utcnow()
    if now > time_sent:
        raise Value_Error("Time sent is a time in the past")

    data = add_message(channel_id, message_id, user['u_id'], message,
                       time_sent)

    save(data)
    return {'message_id': message_id}
示例#8
0
def uploadphoto(token, img_url, x_start, y_start, x_end, y_end):
    ''' Given a URL of an image on the internet, crops the image within
    bounds (x_start, y_start) and (x_end, y_end). Position (0,0) is the top left. '''
    if urllib.request.urlopen(img_url).getcode() != 200:
        raise Value_Error("img_url is returns an HTTP status other than 200.")

    if not img_url.lower().endswith('.jpg'):
        raise Value_Error("img_url is returns an HTTP status other than 200.")

    img_addr = './server/user_image/' + str(token) + '.jpg'
    urllib.request.urlretrieve(img_url, img_addr)
    imageObject = Image.open(img_addr)
    width, height = imageObject.size

    if x_end not in range(width + 1) or y_end not in range(
            height +
            1) or x_start not in range(x_end) or y_start not in range(y_end):
        os.remove(img_addr)
        raise Value_Error(
            "any of x_start, y_start, x_end, y_end are not within the dimensions of the image at the URL."
        )

    cropped = imageObject.crop((x_start, y_start, x_end, y_end))
    cropped.save(img_addr)
    data = getData()
    user_id = getUserFromToken(token)
    data['users'][user_id]['profile_img_url'] = '/user_image?file=' + str(
        token) + '.jpg'
    save(data)
    return {}
示例#9
0
def login(email, password):
    """ Given a registered users' email and password and generates
    a valid token for the user to remain authenticated """
    data = getData()
    len_user = len(data['users'])
    right_user = None
    if len_user > 0:
        len_user -= 1

    if re.search(CHECK_EMAIL, email):
        for user in data['users']:
            if user['email'] == email:
                right_user = user

        if right_user is None:
            raise Value_Error("Email entered does not belong to a user")

        if right_user['password'] != str(
                sha256(password.encode()).hexdigest()):
            raise Value_Error("Password is not correct")
    else:
        raise Value_Error("Email entered is not a valid email")

    right_user['loggedIn'] = True
    save(data)
    return {
        'u_id': right_user['u_id'],
        'token': generateToken(right_user['u_id'])
    }
示例#10
0
def sethandle(token, handle):
    ''' Update the authorised user's handle (i.e. display name) '''
    data = getData()
    user_id = getUserFromToken(token)

    for user in data['users']:
        if user['handle'] == handle:
            raise Value_Error("handle is already used by another user")

    if len(handle) < 3 or len(handle) > 20:
        raise Value_Error("handle_str must be between 3 and 20 characters")

    data['users'][user_id]['handle'] = handle

    save(data)
    return {}
示例#11
0
def setemail(token, email):
    ''' Update the authorised user's email address '''
    data = getData()
    user_id = getUserFromToken(token)

    for user in data['users']:
        if user['email'] == email:
            raise Value_Error(
                "Email address is already being used by another user")

    if (re.search(CHECK_EMAIL, email)):
        data['users'][user_id]['email'] = email
    else:
        raise Value_Error("Email entered is not a valid email")

    save(data)
    return {}
示例#12
0
def setname(token, name_first, name_last):
    '''Update the authorised user's first and last name'''
    data = getData()
    user_id = getUserFromToken(token)

    if len(name_first) not in range(1, 51):
        raise Value_Error(
            "name_first is not between 1 and 50 characters in length")
    if len(name_last) not in range(1, 51):
        raise Value_Error(
            "name_last is not between 1 and 50 characters in length")

    data['users'][user_id]['name_first'] = name_first
    data['users'][user_id]['name_last'] = name_last

    save(data)
    return {}
示例#13
0
def permission(token, u_id, permission_id):
    ''' Given a User by their user ID, set their permissions to
    new permissions described by permission_id '''
    data = getData()
    if permission_id not in range(0, 4):
        raise Value_Error("permission_id does not refer to a value permission")

    if u_id not in range(len(data['users'])):
        raise Value_Error(f"u_id: {u_id} does not refer to a valid user.")

    user_id = getUserFromToken(token)
    admin_or_owner = data['users'][user_id]
    if admin_or_owner['permission'] == 3:
        raise Value_Error("The authorised user is not an admin or owner")

    data['users'][int(u_id)]['permission'] = permission_id
    save(data)
    return {}
示例#14
0
def passwordreset_reset(reset_code, new_password):
    ''' Given a reset code for a user, set that user's
    new password to the password provided '''
    data = getData()

    if len(new_password) in range(6):
        raise Value_Error("Password entered is not a valid password")

    valid_code = True
    for user in data['users']:
        if user['reset_code'] == reset_code:
            valid_code = False
            user['password'] = str(sha256(new_password.encode()).hexdigest())
            user['reset_code'] = None

    if valid_code:
        raise Value_Error("reset_code is not a valid reset code")
    save(data)
    return {}
示例#15
0
def remove(token, message_id):
    ''' Given a message_id for a message, this
    message is removed from the channel '''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    message_index = find_message(message_id)

    if message_index is None:
        raise Value_Error(f"Message (based on ID) no longer exists")
    message = data['messages'][message_index]

    if user['u_id'] != message['u_id'] and int(
            user['permission']) not in range(1, 3):
        raise Value_Error(
            "Message with message_id was not sent by the authorised user making this request and The authorised user is not an admin or owner of this channel or the slackr"
        )

    data['messages'].remove(message)
    save(data)
    return {}
示例#16
0
def standup_start(token, channel_id, length):
    '''For a given channel, start the standup period whereby for the
    next 15 minutes if someone calls "standup_send" with a message,
    it is buffered during the 15 minute window then at the end of the
    15 minute window a message will be added to the message queue in
    the channel from the user who started the standup.'''
    data = getData()
    right_channel_index = find_channel(channel_id)
    now_time = dt.utcnow()

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    right_channel = data['channels_list'][right_channel_index]

    if not inChannel(token, channel_id):
        raise AccessError(
            'The authorised user is not a member of the channel that the message is within'
        )

    if standup_active(token, channel_id)['is_active'] is False:
        time_finish = now_time + timedelta(seconds=int(length))
        message = sendlater(token, channel_id, '', time_finish)

        # update data
        data = getData()
        right_channel_index = find_channel(channel_id)
        right_channel = data['channels_list'][right_channel_index]
        right_channel['standup']['finish_time'] = time_finish
        right_channel['standup']['message_id'] = message['message_id']
    else:
        raise Value_Error(
            'An active standup is currently running in this channel')

    save(data)
    return {
        'time_finish': time_finish.replace(tzinfo=timezone.utc).timestamp()
    }
示例#17
0
def addowner(token, channel_id, u_id):
    ''' Make user with user id u_id an owner of this channel '''
    data = getData()
    maker_id = getUserFromToken(token)
    maker = data['users'][maker_id]
    joiner = data['users'][int(u_id)]
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]

    joiner_detail = user_detail(joiner['u_id'], joiner['name_first'], joiner['name_last'], joiner['profile_img_url'])
    maker_detail = user_detail(maker['u_id'], maker['name_first'], maker['name_last'], maker['profile_img_url'])

    if (maker_detail not in right_channel['owners']) and (maker['permission'] != 1):
        raise AccessError("you don't have the right to access")

    if joiner_detail in right_channel['owners']:
        raise Value_Error("the user id is already an owner")

    right_channel['owners'].append(joiner_detail)
    save(data)
    return {}
示例#18
0
def messages(token, channel_id, start):
    '''Given a Channel with ID channel_id that the authorised user is part of,
    return up to 50 messages between index "start" and "start + 50".
    Message with index 0 is the most recent message in the channel.
    This function returns a new index "end" which is the value of "start + 50",
    or, if this function has returned the least recent messages in the channel,
    returns -1 in "end" to indicate there are no more messages to load after this return.'''
    data = getData()
    u_id = getUserFromToken(token)
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]
    now = dt.utcnow()
    message_list = []
    total_message = 0
    for message in data['messages']:
        if int(message['channel_id']) == int(channel_id) and now >= message['time_created']:
            tmp = message
            tmp['time_created'] = message['time_created'].replace(tzinfo=timezone.utc).timestamp()
            for reaction in tmp['reacts']:
                reaction['is_this_user_reacted'] = (u_id in reaction['u_ids'])
            message_list.append(tmp)
            total_message += 1
        if message['message'] == '':
            data['messages'].remove(message)

    if int(start) != 0 and int(start) >= total_message:
        raise Value_Error("start is greater than or equal to the total number of messages in the channel")

    if not inChannel(token, channel_id):
        raise AccessError("Authorised user is not a member of channel with channel_id")

    end = int(start) + 50
    if end > total_message:
        end = -1
    return {'messages': message_list[int(start):int(start)+50], 'start': int(start), 'end': end}
示例#19
0
def profile(token, u_id):
    ''' For a valid user, returns information about their email,
    first name, last name, and handle '''
    data = getData()
    if int(u_id) not in range(len(data['users'])):
        raise Value_Error(f"u_id: {u_id} does not refer to a valid user.")

    user = data['users'][int(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']
    }
示例#20
0
def details(token, channel_id):
    '''
    Given a Channel with ID channel_id that the authorised
    user is part of, provide basic details about the channel
    '''
    data = getData()
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]

    if not inChannel(token, channel_id):
        raise AccessError("Authorised user is not a member of channel with channel_id.")

    return {
        'name': right_channel['channel']['name'],
        'owner_members': right_channel['owners'],
        'all_members': right_channel['members']
    }
示例#21
0
def send(token, channel_id, message):
    ''' Send a message from authorised_user to the
    channel specified by channel_id '''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    message_id = get_new_message_id()
    if len(message) > 1000:
        raise Value_Error("Message is more than 1000 characters")

    if not inChannel(token, channel_id):
        raise AccessError(
            "the authorised user has not joined the channel they are trying to post to"
        )

    data = add_message(channel_id, message_id, user['u_id'], message,
                       dt.utcnow())

    save(data)
    return {'message_id': message_id}
示例#22
0
def standup_active(token, channel_id):
    ''' For a given channel, return whether a standup is active in it,
    and what time the standup finishes. If no standup is active,
    then time_finish returns None '''
    data = getData()
    right_channel_index = find_channel(channel_id)

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    right_channel = data['channels_list'][right_channel_index]
    finish_time = right_channel['standup']['finish_time']
    is_active = True
    if right_channel['standup']['finish_time'] < dt.utcnow():
        is_active = False

    return {
        'is_active': is_active,
        'time_finish': finish_time.replace(tzinfo=timezone.utc).timestamp()
    }
示例#23
0
def leave(token, channel_id):
    ''' Given a channel ID, the user removed as a member of this channel '''
    data = getData()
    user_id = getUserFromToken(token)
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]

    # remove channel from user's channel list
    if right_channel['channel'] in data['users'][user_id]['user_channel']:
        data['users'][user_id]['user_channel'].remove(right_channel['channel'])

    # remove user from channel's member list
    for member in right_channel['members']:
        if data['users'][user_id]['u_id'] == member['u_id'] and member in right_channel['members']:
            right_channel['members'].remove(member)
            break

    save(data)
    return {}
示例#24
0
def removeowner(token, channel_id, u_id):
    ''' Remove user with user id u_id an owner of this channel '''
    data = getData()
    maker_id = getUserFromToken(token)
    maker = data['users'][maker_id]
    unlucky = data['users'][int(u_id)]
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]

    unlucky_detail = user_detail(unlucky['u_id'], unlucky['name_first'], unlucky['name_last'], unlucky['profile_img_url'])
    maker_detail = user_detail(maker['u_id'], maker['name_first'], maker['name_last'], maker['profile_img_url'])

    if (maker_detail not in right_channel['owners']) and (maker['permission'] != 1):
        raise AccessError("you don't have the right to access")

    if unlucky_detail in right_channel['owners']:
        if len(right_channel['owners']) > 1:
            right_channel['owners'].remove(unlucky_detail)

    save(data)
    return {}
示例#25
0
def join(token, channel_id):
    ''' Given a channel_id of a channel that the authorised
    user can join, adds them to that channel '''
    data = getData()
    joiner_id = getUserFromToken(token)
    joiner = data['users'][joiner_id]
    right_channel_index = find_channel(channel_id)
    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")
    right_channel = data['channels_list'][right_channel_index]

    if not right_channel['is_public']:
        raise AccessError("a private channel can only be joined by invitation")

    if right_channel['channel'] not in joiner['user_channel']:
        joiner['user_channel'].append(right_channel['channel'])

    joiner_info = user_detail(joiner['u_id'], joiner['name_first'], joiner['name_last'], joiner['profile_img_url'])

    if joiner_info not in right_channel['members']:
        right_channel['members'].append(joiner_info)

    save(data)
    return {}
示例#26
0
def 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 handle is already taken,
    a number is added to the end of the handle to make it unique. '''
    data = getData()
    token = generateToken(len(data['users']))
    if not (re.search(CHECK_EMAIL, email)):
        raise Value_Error("the email is invalid")

    for user in data['users']:
        if user['email'] == email:
            raise Value_Error(
                "Email address is already being used by another user")

    if len(password) in range(1, 6):
        raise Value_Error(
            "password is below 6 characters characters in length")

    if len(name_first) not in range(1, 51):
        raise Value_Error(
            "name_first is not between 1 and 50 characters in length")

    if len(name_last) not in range(1, 51):
        raise Value_Error(
            "name_last is not between 1 and 50 characters in length")

    user_id = len(data['users'])

    permission_id = 3
    if user_id == 0:
        permission_id = 1

    handle = (name_first + name_last).lower()
    if len(handle) < 3:
        handle = str(user_id) + handle
        handle = handle[:(20 - len(str(user_id)))] + str(user_id)

    for user in data['users']:
        if user['handle'] == handle[:20]:
            handle = str(user_id) + handle
            handle = handle[:(20 - len(str(user_id)))] + str(user_id)
            break

    data['users'].append({
        'u_id': user_id,
        'email': email,
        'password': str(sha256(password.encode()).hexdigest()),
        'name_first': name_first,
        'name_last': name_last,
        'handle': str(handle[:20]),
        'profile_img_url': '/user_image?file=default.jpg',
        'permission': permission_id,
        'user_channel': [],
        'reset_code': None,
        'loggedIn': False
    })

    save(data)
    return {'u_id': user_id, 'token': token}