예제 #1
0
async def create_group_invitation(req: request, user_id: int, group_id: int):
    """
    POST /group/invitation/<group_id:int>
    creates a invitation code for a group
    :param req:
    :param user_id:
    :param group_id:
    :return:
    """
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            code_exists = True
            while code_exists:
                invitation_code = uuid.uuid4().hex
                code_exists = len(
                    await connection.fetch('SELECT id FROM group_invitations WHERE code=$1', invitation_code)
                ) > 0
            try:
                expires_at = datetime.fromtimestamp(int(req.form['expires_at'][0])) if 'expires_at' in req.form else None
                max_uses = int(req.form['max_uses'][0]) if 'max_uses' in req.form else 0
            except TypeError:
                return json_r({"error": "Invalid parameters"}, 400)
            except ValueError:
                return json_r({"error": "Timestamp must be a valid integer"}, 400)

            await connection.execute(
                'INSERT INTO group_invitations(code, group_id, created_by, expires_at, max_uses) ' +
                'VALUES($1,$2,$3,$4,$5)',
                invitation_code,
                group_id,
                user_id,
                expires_at,
                max_uses
            )
    return json_r({"success": True, "code": invitation_code})
예제 #2
0
async def login_user(req: request):
    """
    Tries to login an user, if success, return its JWT
    :param req:
    :return:
    """
    if 'username' not in req.form or 'password' not in req.form:
        return json_r({"error": "Username or password not sent"}, 400)
    # Do login to the user
    async with req.app.pool.acquire() as connection:
        # Open a transaction.
        async with connection.transaction():
            # Run the query passing the request argument.
            user_search = await connection.fetch(
                "SELECT * FROM users WHERE username=$1",
                req.form["username"][0]
            )
            if len(user_search) == 0:
                return json_r({"error": "Invalid credentials"}, 400)

            user_password = user_search[0]["password"]
            if not pbk.verify(req.form["password"][0], user_password):
                return json_r({"error": "Invalid credentials"}, 400)

            token_payload = {
                "user": user_search[0]["id"],
                "expires_in": 7200,
                "expires_at": int(time.time()) + 7200
            }
            return json_r({"token": jwt.encode(token_payload, req.app.app_config["key"], algorithm='HS256')})
예제 #3
0
async def register_user(req: request):
    """
    Tries to register an user inside the app. As long as the username doesn't exists already
    :param req:
    :return:
    """
    if 'username' not in req.form or 'password' not in req.form:
        return json_r({"error": "Username or password not sent"}, 400)
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            # Check if the user already exists
            user_search = await connection.fetch(
                "SELECT * FROM users WHERE username=$1",
                req.form["username"][0]
            )
            # If exists, then return error
            if len(user_search) != 0:
                return json_r({"error": "Username already exists"}, 400)

            # Register the user
            await connection.execute(
                "INSERT INTO users(username, password) VALUES($1,$2)",
                req.form["username"][0], pbk.hash(req.form["password"][0])
            )
            return json_r({"success": True})
예제 #4
0
async def quit_from_group(req: request, user_id: int, group_id: int):
    """
    POST /group/exit/<group_id:int>
    Exits from a group
    :param req:
    :param user_id:
    :param group_id:
    :return:
    """
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            group_info = await connection.fetch(
                'SElECT id FROM groups WHERE id=$1 AND created_by=$2',
                group_id,
                user_id
            )

            if len(group_info) > 0:
                # Is the owner of the group, so no
                return json_r({"error": "You are the owner of this group, delete it instead"}, 400)

            # Delete from the group
            await connection.execute('DELETE FROM belongs_to_group WHERE group_id=$1 AND user_id=$2', group_id, user_id)

            return json_r({"success": True}, 200)
예제 #5
0
        async def is_logged(req: request, *args, **kwargs):
            if not req.headers.get("dango-key"):
                return json_r({"error": "Unauthorized"}, 401)

            # Get the token owner
            owner = await auth_helpers.token_owner(req.headers.get("dango-key"), req)

            # invalid owner or expired token
            if owner == -1:
                return json_r({"error": "Unauthorized"}, 401)

            # Check all the permissions
            for permission in permissions:
                if permission in auth_helpers.permission_check:
                    check = await auth_helpers.permission_check[permission](owner, req, *args, **kwargs)
                    if not check:
                        return json_r({"error": "Unauthorized"}, 401)
                else:
                    print(f'Permission check for {permission} not implemented')

            # Execute the function
            if send_user_id:
                resp = await fn(req, owner, *args, **kwargs)
            else:
                resp = await fn(req, *args, **kwargs)
            return resp
예제 #6
0
async def user_info(req: request, user_id: int):
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            # Check if the user already exists
            user_search = await connection.fetch(
                "SELECT id, username FROM users WHERE id=$1",
                user_id
            )
            if len(user_search) == 0:
                return json_r({"user": {}})
            user_details = dict(user_search[0])
            return json_r({"user": user_details})
예제 #7
0
async def get_user_groups(req: request, user_id: int):
    """
    Get all groups
    :param req:
    :param user_id:
    :return:
    """
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            order_by, order_type = get_sorting_params(req)
            limit, page = get_limit_and_page(req)

            groups = await connection.fetch(
                f'SELECT g.group_name, g.created_at, g.updated_at, u.username from (SELECT * FROM groups INNER JOIN belongs_to_group ON groups.id=belongs_to_group.group_id AND belongs_to_group.user_id=$1) as g INNER JOIN users AS u ON u.id=g.created_by ORDER BY {order_by} {order_type} LIMIT $2 OFFSET $3',
                user_id,
                limit,
                (page - 1) * limit
            )
            total_groups = (await connection.fetch(
                'SELECT count(group_id) FROM belongs_to_group WHERE user_id=$1',
                user_id
            ))[0]['count']
            return json_r({
                "total": total_groups,
                "items_per_page": limit,
                "groups": [dict(g) for g in groups]
            })
예제 #8
0
async def get_group_participants(req: request):
    """
    Get all persons that belongs to a group
    :param req:
    :return:
    """
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            group_id = int(req.args['group-id'][0])
            limit, page = get_limit_and_page(req)
            users = await connection.fetch(
                'SELECT users.username from belongs_to_group INNER JOIN users ON users.id=belongs_to_group.user_id WHERE group_id=$1 ORDER BY username asc LIMIT $2 OFFSET $3',
                group_id,
                limit,
                (page-1)*limit
            )
            total_users = (await connection.fetch(
                'SELECT count(user_id) FROM belongs_to_group WHERE group_id=$1',
                group_id
            ))[0]['count']

            return json_r({
                "total": total_users,
                "items_per_page": limit,
                "users": [dict(u) for u in users]
            })
예제 #9
0
async def get_user_group_invitations(req: request, user_id: int):
    """
    GET /group/invitation?group-id=<id>
    :param req:
    :param user_id:
    :param group_id:
    :return:
    """
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            invitations = await connection.fetch(
                "SELECT * FROM group_invitations WHERE group_id=$1 AND created_by=$2",
                int(req.args['group-id'][0]),
                user_id
            )
            user_invitations = {"invitations": [*map(
                lambda invitation: {
                    "code": invitation["code"],
                    "max_uses":invitation["max_uses"],
                    "current_uses": invitation["current_uses"],
                    "expires_at": invitation["expires_at"]
                },
                invitations
            )]}
    return json_r(user_invitations, 200)
예제 #10
0
        async def is_logged(req: request, *args, **kwargs):
            if not req.headers.get("dango-key"):
                return json_r({"error": "Unauthorized"}, 401)

            # Get the token owner
            owner = await auth_helpers.token_owner(req.headers.get("dango-key"), req)

            # invalid owner or expired token
            if owner == -1:
                return json_r({"error": "Unauthorized"}, 401)

            # Execute the function
            if send_user_id:
                resp = await fn(req, owner, *args, **kwargs)
            else:
                resp = await fn(req, *args, **kwargs)
            return resp
예제 #11
0
async def user_info_detailed(req: request, user_id: int):
    """
    Get the details of an specified user
    :param req:
    :param user_id:
    :return:
    """
    # TODO - Shares at least one group with the user
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            # Check if the user already exists
            user_search = await connection.fetch(
                "SELECT id, username FROM users WHERE id=$1",
                user_id
            )
            if len(user_search) == 0:
                return json_r({"user": {}})
            user_details = dict(user_search[0])
            return json_r({"user": user_details})
예제 #12
0
async def delete_group(req: request, user_id: int, group_id: int):
    """
    DELETE /group/<group_id:int>
    Deletes a group and all users belonging to it
    :param req:
    :param user_id:
    :param group_id:
    :return:
    """
    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            await connection.execute('DELETE FROM groups WHERE id=$1', group_id)
    return json_r({"success": True})
예제 #13
0
async def create_group(req: request, user_id: int):
    """
    POST /group
    Creates a new group for the desired user
    :param req:
    :param user_id:
    :return:
    """
    if 'name' not in req.form or len(req.form['name']) != 1:
        return json_r({"error": "Invalid parameters"}, 400)
    name = req.form['name'][0]
    if not isinstance(name, str):
        return json_r({"error": "Invalid parameters"}, 400)

    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            group_search = await connection.fetch(
                "SELECT * FROM groups WHERE created_by=$1 AND group_name=$2",
                user_id,
                name
            )
            if len(group_search) > 0:
                return json_r({"error": "You have already created a group with that name"}, 400)

            group_insert = await connection.fetch(
                "INSERT INTO groups(created_by, group_name) VALUES($1,$2) RETURNING id",
                user_id,
                name
            )
            group_id = group_insert[0]["id"]
            # insert into reference, so its known that the user belongs to that group
            await connection.execute(
                "INSERT INTO belongs_to_group(user_id, group_id) VALUES ($1, $2)",
                user_id,
                group_id
            )
    return json_r({"success": True, "id": group_id})
예제 #14
0
async def join_to_group(req: request, user_id: int):
    """
    POST /group/join
    Joins to a group. The invite of the group is required
    :param req:
    :param user_id:
    :return:
    """
    if 'code' not in req.form or len(req.form['code']) > 1:
        return json_r({"error": "Invalid parameters"}, 400)

    async with req.app.pool.acquire() as connection:
        async with connection.transaction():
            code = req.form['code'][0]
            invitation_info = await connection.fetch(
                'SELECT * FROM group_invitations WHERE code=$1',
                code
            )

            if len(invitation_info) == 0:
                # Invalid code
                return json_r({"error": "Invalid invitation"}, 400)

            max_uses = int(invitation_info[0]['max_uses'])
            current_uses = int(invitation_info[0]['current_uses'])
            group_id = int(invitation_info[0]['group_id'])

            if invitation_info[0]['expires_at'] is not None and int(time.time()) > int(invitation_info[0]['expires_at']):
                # Expired invitation
                return json_r({"error": "Expired invitation"}, 400)
            elif max_uses != 0 and max_uses <= current_uses:
                # All invitation uses consumed
                return json_r({"error": "Expired invitation"}, 400)

            # Check if the user already belongs to that group
            already_belongs = len(await connection.fetch(
                "SELECT * FROM belongs_to_group WHERE user_id=$1 AND group_id=$2",
                user_id,
                group_id
            )) > 0
            if already_belongs:
                return json_r({"error": "You already belong to that group"}, 400)

            # Not inside the group, so let's join in
            await connection.execute('INSERT INTO belongs_to_group(group_id, user_id) VALUES($1,$2)', group_id, user_id)
            if max_uses != 0:
                # increment the code if necessary
                await connection.execute('UPDATE group_invitations SET current_uses=current_uses+1 WHERE code=$1', code)

            # Get the group info so we can return it
            group_info = (await connection.fetch('SElECT id, group_name, created_at FROM groups WHERE id=$1', group_id))[0]

            return json_r({"success": True, "group": group_info})