Esempio n. 1
0
    def view_helper(self, user_id: str, args: Namespace) -> ResponseTuple:
        """
        View user info from database.

        If no parameters are provided, returns information of ``user_id``. If
        ``args.username`` is provided, returns the specific user
        matching the Slack ID provided, otherwise returns all users that match
        all traits of other provided parameters (e.g. ``github`` and ``email``)

        :param user_id: Slack ID of user who is calling command
        :param args: List of user parameters defining the query
        :return: error message if user not found in database, else information
                 about the user, or users.
        """
        try:
            if args.username:
                user = self.facade.retrieve(User, args.username)
            # If no query parameters are provided, get the sender
            elif not args.github and not args.email:
                user = self.facade.retrieve(User, user_id)
            else:
                query = []
                if args.github:
                    query.append(('github', args.github))
                if args.email:
                    query.append(('email', escape_email(args.email)))

                users = self.facade.query(User, query)
                if len(users) == 0:
                    raise LookupError
                elif len(users) > 1:
                    return {
                        'text': 'Warning - multiple users found!',
                        'attachments': [u.get_attachment() for u in users]
                    }, 200
                else:
                    user = users[0]

            if args.inspect:
                return {
                    'attachments':
                    [user.get_attachment(),
                     self.viewinspect_helper(user)]
                }, 200
            else:
                return {'attachments': [user.get_attachment()]}, 200
        except LookupError:
            return self.lookup_error, 200
Esempio n. 2
0
    def user_edit(self,
                  caller_id: str,
                  member: str = None,
                  name: str = None,
                  email: str = None,
                  pos: str = None,
                  github: str = None,
                  major: str = None,
                  bio: str = None,
                  permission: Permissions = None) -> bool:
        """
        Edit a user in the database.

        If ``member`` is not None, and the calling user is an admin, this
        function edits the user with ID ``member``. Otherwise, the calling
        user is edited.

        :param caller_id: Slack ID of the user who is calling the API
        :param member: Slack ID of the user to edit
        :param name: display name to change to for the user
        :param email: email to change to for the user
        :param pos: position to change to for the user
        :param github: Github username to change to for the user
        :param major: major to change to for the user
        :param bio: bio to change to for the user
        :param permission: permission level to change to for the user
        :raises: LookupError if the calling user or the desired user to edit
                 could not be found in the database
        :raises: PermissionError if the calling user is attempting to edit
                 another user and they are not an admin, or are trying to
                 edit their own permission level without being an admin
        :raises: GithubAPIException if setting the Github username fails to
                 add the corresponding user to the Github organization
        :return: True if user was successfully edited in the database,
                 False otherwise
        """
        logging.info("User edit command API called")

        calling_user = self._db_facade.retrieve(User, caller_id)

        is_admin = calling_user.permissions_level == Permissions.admin
        edited_user = calling_user

        if member is not None:
            if is_admin:
                edited_user = self._db_facade.retrieve(User, member)
            else:
                msg = f"Calling user with Slack ID {caller_id} has" \
                    " permission level " \
                    f"{str(calling_user.permissions_level)}, insufficient " \
                    "for editing another user!"
                logging.error(msg)
                raise PermissionError(msg)
        else:
            edited_user = calling_user

        if permission and is_admin:
            edited_user.permissions_level = permission
        elif permission and not is_admin:
            msg = f"Calling user with Slack ID {caller_id} has permission" \
                f" level {str(calling_user.permissions_level)}, " \
                "insufficient for editing own permission level!"
            logging.error(msg)
            raise PermissionError(msg)
        if github:
            github_id = self._gh_interface.org_add_member(github)
            edited_user.github_username = github
            edited_user.github_id = github_id
        if name:
            edited_user.name = name
        if email:
            edited_user.email = escape_email(email)
        if pos:
            edited_user.position = pos
        if major:
            edited_user.major = major
        if bio:
            edited_user.biography = bio

        return self._db_facade.store(edited_user)
Esempio n. 3
0
    def edit_helper(self,
                    user_id: str,
                    param_list: Dict[str, str]) -> ResponseTuple:
        """
        Edit user from database.

        If ``param_list['member'] is not None``, this function edits using the
        ID from ``param_list['member']`` (must be an admin to do so).
        Otherwise, edits the user that called the function.

        :param user_id: Slack ID of user who is calling the command
        :param param_list: List of user parameters that are to be edited
        :return: returns error message if not admin and command
                   edits another user, returns edit message if user is edited
        """
        is_admin = False
        edited_user = None
        msg = ""
        if param_list["member"] is not None:
            try:
                admin_user = self.facade.retrieve(User, user_id)
                if admin_user.permissions_level != Permissions.admin:
                    return self.permission_error, 200
                else:
                    is_admin = True
                    edited_id = param_list["member"]
                    edited_user = self.facade.retrieve(User, edited_id)
            except LookupError:
                return self.lookup_error, 200
        else:
            try:
                edited_user = self.facade.retrieve(User, user_id)
            except LookupError:
                return self.lookup_error, 200

        if param_list["name"]:
            edited_user.name = param_list["name"]
        if param_list["email"]:
            edited_user.email = escape_email(param_list["email"])
        if param_list["pos"]:
            edited_user.position = param_list["pos"]
        if param_list["github"]:
            try:
                github_id = self.github.org_add_member(param_list["github"])
                edited_user.github_username = param_list["github"]
                edited_user.github_id = github_id
            except GithubAPIException:
                msg = f"\nError adding user {param_list['github']} to " \
                      f"GitHub organization"
                logging.error(msg)
        if param_list["major"]:
            edited_user.major = param_list["major"]
        if param_list["bio"]:
            edited_user.biography = param_list["bio"]
        if param_list["permission"] and is_admin:
            edited_user.permissions_level = cast(Permissions,
                                                 param_list["permission"])
        elif param_list["permission"] and not is_admin:
            msg += "\nCannot change own permission: user isn't admin."
            logging.warning(f"User {user_id} tried to elevate permissions"
                            " level.")

        self.facade.store(edited_user)
        ret = {'attachments': [edited_user.get_attachment()]}
        if msg != "":
            # mypy doesn't like the fact that there could be different types
            # for the values of the dict ret, so we have to ignore this line
            # for now
            ret['text'] = msg  # type: ignore
        return ret, 200
Esempio n. 4
0
 def test_escape_normal_email(self):
     email = '*****@*****.**'
     self.assertEqual(util.escape_email(email), email)
Esempio n. 5
0
 def test_escape_email(self):
     """Test parsing escaped emails."""
     email = "<mailto:[email protected]|[email protected]>"
     ret = util.escape_email(email)
     self.assertEqual(ret, "*****@*****.**")
Esempio n. 6
0
def test_escape_email():
    """Test parsing escaped emails."""
    email = "<mailto:[email protected]|[email protected]>"
    ret = util.escape_email(email)
    assert ret == "*****@*****.**"
Esempio n. 7
0
    def edit_helper(self, user_id: str, args: Namespace) -> ResponseTuple:
        """
        Edit user from database.

        If ``args.username is not None``, this function edits using
        the ID from ``args.username`` (must be an admin to do so).
        Otherwise, edits the user that called the function.

        :param user_id: Slack ID of user who is calling the command
        :param args: List of user parameters that are to be edited
        :return: error message if not admin and command edits another user,
            or the edit message if user is edited
        """
        is_admin = False
        edited_user = None
        msg = ""
        if args.username is not None:
            try:
                admin_user = self.facade.retrieve(User, user_id)
                if admin_user.permissions_level != Permissions.admin:
                    return self.permission_error, 200
                else:
                    is_admin = True
                    edited_id = args.username
                    edited_user = self.facade.retrieve(User, edited_id)
            except LookupError:
                return self.lookup_error, 200
        else:
            try:
                edited_user = self.facade.retrieve(User, user_id)
            except LookupError:
                return self.lookup_error, 200

        if args.name:
            edited_user.name = args.name
        if args.email:
            edited_user.email = escape_email(args.email)
        if args.pos:
            edited_user.position = args.pos
        if args.github:
            try:
                github_id = self.github.org_add_member(args.github)
                edited_user.github_username = args.github
                edited_user.github_id = github_id
            except GithubAPIException:
                msg = f"\nError adding user {args.github} to " \
                      f"GitHub organization"
                logging.error(msg)
        if args.major:
            edited_user.major = args.major
        if args.bio:
            edited_user.biography = args.bio
        if args.permission and is_admin:
            edited_user.permissions_level = args.permission
        elif args.permission and not is_admin:
            msg += "\nCannot change own permission: user isn't admin."
            logging.warning(f"User {user_id} tried to elevate permissions"
                            " level.")

        self.facade.store(edited_user)

        # Sync permissions only if email was updated
        if args.email:
            sync_user_email_perms(self.gcp, self.facade, edited_user)

        ret = {'attachments': [edited_user.get_attachment()]}
        if msg != "":
            # mypy doesn't like the fact that there could be different types
            # for the values of the dict ret, so we have to ignore this line
            # for now
            ret['text'] = msg  # type: ignore
        return ret, 200