示例#1
0
    def accept_reject_join_request(team_id, from_user_id, username, function,
                                   action):
        from_user = UserService.get_user_by_id(from_user_id)
        to_user_id = UserService.get_user_by_username(username).id
        team = TeamService.get_team_by_id(team_id)
        MessageService.accept_reject_request_to_join_team(
            from_user_id, from_user.username, to_user_id, team.name, team_id,
            action)

        is_member = TeamService.is_user_team_member(team_id, to_user_id)
        if action == "accept":
            if is_member:
                TeamService.activate_team_member(team_id, to_user_id)
            else:
                TeamService.add_team_member(
                    team_id,
                    to_user_id,
                    TeamMemberFunctions[function.upper()].value,
                    True,
                )
        elif action == "reject":
            if is_member:
                TeamService.delete_invite(team_id, to_user_id)
        else:
            raise TeamServiceError("Invalid action type")
    def send_message_after_chat(chat_from: int, chat: str, project_id: int):
        """ Send alert to user if they were @'d in a chat message """
        current_app.logger.debug("Sending Message After Chat")
        usernames = MessageService._parse_message_for_username(
            chat, project_id)

        if len(usernames) == 0:
            return  # Nobody @'d so return

        link = MessageService.get_project_link(project_id,
                                               include_chat_section=True)

        messages = []
        for username in usernames:
            current_app.logger.debug(f"Searching for {username}")
            try:
                user = UserService.get_user_by_username(username)
            except NotFound:
                current_app.logger.error(f"Username {username} not found")
                continue  # If we can't find the user, keep going no need to fail

            message = Message()
            message.message_type = MessageType.MENTION_NOTIFICATION.value
            message.project_id = project_id
            message.from_user_id = chat_from
            message.to_user_id = user.id
            message.subject = f"You were mentioned in {link} chat"
            message.message = chat
            messages.append(dict(message=message, user=user))

        MessageService._push_messages(messages)

        query = (
            """ select user_id from project_favorites where project_id = :project_id"""
        )
        result = db.engine.execute(text(query), project_id=project_id)
        favorited_users = [r[0] for r in result]

        if len(favorited_users) != 0:
            project_link = MessageService.get_project_link(
                project_id, include_chat_section=True)
            # project_title = ProjectService.get_project_title(project_id)
            messages = []
            for user_id in favorited_users:

                try:
                    user = UserService.get_user_dto_by_id(user_id)
                except NotFound:
                    continue  # If we can't find the user, keep going no need to fail

                message = Message()
                message.message_type = MessageType.PROJECT_CHAT_NOTIFICATION.value
                message.project_id = project_id
                message.to_user_id = user.id
                message.subject = f"{chat_from} left a comment in {project_link}"
                message.message = chat
                messages.append(dict(message=message, user=user))

            # it's important to keep that line inside the if to avoid duplicated emails
            MessageService._push_messages(messages)
示例#3
0
 def send_invite(team_id, from_user_id, username):
     to_user = UserService.get_user_by_username(username)
     from_user = UserService.get_user_by_id(from_user_id)
     team = TeamService.get_team_by_id(team_id)
     MessageService.send_invite_to_join_team(from_user_id,
                                             from_user.username, to_user.id,
                                             team.name, team_id)
    def send_message_after_comment(comment_from: int, comment: str,
                                   task_id: int, project_id: int):
        """ Will send a canned message to anyone @'d in a comment """
        usernames = MessageService._parse_message_for_username(
            comment, project_id)
        if len(usernames) != 0:
            task_link = MessageService.get_task_link(project_id, task_id)

            messages = []
            for username in usernames:

                try:
                    user = UserService.get_user_by_username(username)
                except NotFound:
                    continue  # If we can't find the user, keep going no need to fail

                message = Message()
                message.message_type = MessageType.MENTION_NOTIFICATION.value
                message.project_id = project_id
                message.task_id = task_id
                message.from_user_id = comment_from
                message.to_user_id = user.id
                message.subject = f"You were mentioned in a comment in {task_link} of Project {project_id}"
                message.message = comment
                messages.append(dict(message=message, user=user))

            MessageService._push_messages(messages)

        # Notify all contributors except the user that created the comment.
        results = (TaskHistory.query.with_entities(
            TaskHistory.user_id.distinct()
        ).filter(TaskHistory.project_id == project_id).filter(
            TaskHistory.task_id == task_id).filter(
                TaskHistory.user_id != comment_from).filter(
                    TaskHistory.action == TaskAction.STATE_CHANGE.name).all())
        contributed_users = [r[0] for r in results]

        if len(contributed_users) != 0:
            user_from = User.query.get(comment_from)
            if user_from is None:
                raise ValueError("Username not found")

            task_link = MessageService.get_task_link(project_id, task_id)
            messages = []
            for user_id in contributed_users:
                try:
                    user = UserService.get_user_dto_by_id(user_id)
                except NotFound:
                    continue  # If we can't find the user, keep going no need to fail

                message = Message()
                message.message_type = MessageType.TASK_COMMENT_NOTIFICATION.value
                message.project_id = project_id
                message.task_id = task_id
                message.to_user_id = user.id
                message.subject = f"{user_from.username} left a comment in {task_link} of Project {project_id}"
                message.message = comment
                messages.append(dict(message=message, user=user))

            MessageService._push_messages(messages)
示例#5
0
    def assert_validate_members(team_dto: TeamDTO):
        """ Validates that the users exist"""
        if len(team_dto.members) == 0:
            raise TeamServiceError("Must have at least one member")

            members = []
            managers = 0
            for member in team_dto.members:
                try:
                    UserService.get_user_by_username(member["name"])
                except NotFound:
                    raise NotFound(f'User {member["name"]} does not exist')
                if member["function"] == TeamMemberFunctions.MANAGER.name:
                    managers += 1

                members.append(member)

            if managers == 0:
                raise TeamServiceError(
                    "Must have at least one manager in team")

            team_dto.members = members
    def assert_validate_users(organisation_dto: OrganisationDTO):
        """ Validates that the users exist"""
        if organisation_dto.managers and len(organisation_dto.managers) == 0:
            raise OrganisationServiceError("Must have at least one admin")

            managers = []
            for user in organisation_dto.managers:
                try:
                    admin = UserService.get_user_by_username(user)
                except NotFound:
                    raise NotFound(f"User {user} does not exist")

                managers.append(admin.username)

            organisation_dto.managers = managers
    def get_user_invalidated_tasks(
        as_validator,
        username: str,
        preferred_locale: str,
        closed=None,
        project_id=None,
        page=1,
        page_size=10,
        sort_by="updated_date",
        sort_direction="desc",
    ) -> InvalidatedTasks:
        """ Get invalidated tasks either mapped or invalidated by the user """
        user = UserService.get_user_by_username(username)
        query = (
            TaskInvalidationHistory.query.filter_by(invalidator_id=user.id)
            if as_validator
            else TaskInvalidationHistory.query.filter_by(mapper_id=user.id)
        )

        if closed is not None:
            query = query.filter_by(is_closed=closed)

        if project_id is not None:
            query = query.filter_by(project_id=project_id)

        results = query.order_by(text(sort_by + " " + sort_direction)).paginate(
            page, page_size, True
        )
        project_names = {}
        invalidated_tasks_dto = InvalidatedTasks()
        for entry in results.items:
            dto = InvalidatedTask()
            dto.task_id = entry.task_id
            dto.project_id = entry.project_id
            dto.history_id = entry.invalidation_history_id
            dto.closed = entry.is_closed
            dto.updated_date = entry.updated_date

            if dto.project_id not in project_names:
                project_names[dto.project_id] = ProjectInfo.get_dto_for_locale(
                    dto.project_id, preferred_locale
                ).name
            dto.project_name = project_names[dto.project_id]

            invalidated_tasks_dto.invalidated_tasks.append(dto)

        invalidated_tasks_dto.pagination = Pagination(results)
        return invalidated_tasks_dto
    def transfer_project_to(project_id: int, transfering_user_id: int,
                            username: str):
        """ Transfers project from old owner (transfering_user_id) to new owner (username) """
        project = Project.get(project_id)

        # Check permissions for the user (transferring_user_id) who initiatied the action
        if not ProjectAdminService.is_user_action_permitted_on_project(
                transfering_user_id, project_id):
            raise ValueError("User action not permitted")
        new_owner = UserService.get_user_by_username(username)

        # Check permissions for the new owner - must be an admin or project's org manager or a PM team member
        if not ProjectAdminService.is_user_action_permitted_on_project(
                new_owner.id, project_id):
            raise ValueError("User action not permitted")
        else:
            project.save()
    def _validate_allowed_users(project_dto: ProjectDTO):
        """ Ensures that all usernames are known and returns their user ids """
        if len(project_dto.allowed_usernames) == 0:
            raise ProjectAdminServiceError(
                "Must have at least one allowed user on a private project")

        try:
            allowed_users = []
            for username in project_dto.allowed_usernames:
                user = UserService.get_user_by_username(username)
                allowed_users.append(user)

            # Dynamically attach the user object to the DTO for more efficient persistence
            project_dto.allowed_users = allowed_users
        except NotFound:
            raise ProjectAdminServiceError(
                f"allowedUsers contains an unknown username {user}")
示例#10
0
    def authenticate_email_token(username: str, token: str):
        """ Validate that the email token is valid """
        try:
            user = UserService.get_user_by_username(username)
        except NotFound:
            raise AuthServiceError("Unable to authenticate")

        is_valid, tokenised_email = AuthenticationService.is_valid_token(token, 86400)

        if not is_valid:
            raise AuthServiceError("Unable to authenticate")

        if user.email_address != tokenised_email:
            raise AuthServiceError("Unable to authenticate")

        # Token is valid so update DB and return
        user.set_email_verified_status(is_verified=True)
        return AuthenticationService._get_email_validated_url(True)
示例#11
0
    def join_team(team_id: int,
                  requesting_user: int,
                  username: str,
                  role: str = None):
        is_manager = TeamService.is_user_team_manager(team_id, requesting_user)
        team = TeamService.get_team_by_id(team_id)
        user = UserService.get_user_by_username(username)

        if TeamService.is_user_team_member(team.id, user.id):
            raise TeamJoinNotAllowed(
                "User is already a member of this team or has already requested to join"
            )

        if is_manager:
            if role:
                try:
                    role = TeamMemberFunctions[role.upper()].value
                except KeyError:
                    raise Exception("Invalid TeamMemberFunction")
            else:
                role = TeamMemberFunctions.MEMBER.value

            TeamService.add_team_member(team_id, user.id, role, True)
        else:
            if user.id != requesting_user:
                raise TeamJoinNotAllowed("User not allowed to join team")

            role = TeamMemberFunctions.MEMBER.value

            # active if the team is open
            if team.invite_only:
                active = False
            else:
                active = True

            TeamService.add_team_member(team_id, user.id, role, active)

            if team.invite_only:
                team_managers = team.get_team_managers()
                for member in team_managers:
                    MessageService.send_request_to_join_team(
                        user.id, user.username, member.user_id, team.name,
                        team_id)
示例#12
0
    def accept_reject_invitation_request(team_id, from_user_id, username,
                                         function, action):
        from_user = UserService.get_user_by_id(from_user_id)
        to_user = UserService.get_user_by_username(username)
        team = TeamService.get_team_by_id(team_id)
        team_members = TeamService._get_team_managers(team_id)

        for member in team_members:
            MessageService.accept_reject_invitation_request_for_team(
                from_user_id,
                from_user.username,
                member.user_id,
                to_user.username,
                team.name,
                action,
            )
        if action == "accept":
            TeamService.add_team_member(
                team_id, from_user_id,
                TeamMemberFunctions[function.upper()].value)
示例#13
0
 def get(self, username):
     """
     Get interests by username
     ---
     tags:
       - interests
     produces:
       - application/json
     parameters:
         - in: header
           name: Authorization
           description: Base64 encoded session token
           required: true
           type: string
           default: Token sessionTokenHere==
         - name: username
           in: path
           description: Mapper's OpenStreetMap username
           required: true
           type: string
     responses:
         200:
             description: User interests returned
         404:
             description: User not found
         500:
             description: Internal Server Error
     """
     try:
         user = UserService.get_user_by_username(username)
         interests_dto = UserService.get_interests(user)
         return interests_dto.to_primitive(), 200
     except NotFound:
         return {"Error": "User not found"}, 404
     except Exception as e:
         error_msg = f"UserInterests GET - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
示例#14
0
 def leave_team(team_id, username):
     user = UserService.get_user_by_username(username)
     team_member = TeamMembers.query.filter(
         TeamMembers.team_id == team_id,
         TeamMembers.user_id == user.id).one()
     team_member.delete()
示例#15
0
 def get_project_user_stats(project_id: int, username: str) -> ProjectUserStatsDTO:
     """ Gets the user stats for a specific project """
     project = ProjectService.get_project_by_id(project_id)
     user = UserService.get_user_by_username(username)
     return project.get_project_user_stats(user.id)
示例#16
0
    def send_message_after_chat(chat_from: int, chat: str, project_id: int):
        """ Send alert to user if they were @'d in a chat message """
        # Because message-all run on background thread it needs it's own app context
        app = create_app()
        with app.app_context():
            usernames = MessageService._parse_message_for_username(
                chat, project_id)
            if len(usernames) != 0:
                link = MessageService.get_project_link(
                    project_id, include_chat_section=True)
                messages = []
                for username in usernames:
                    current_app.logger.debug(f"Searching for {username}")
                    try:
                        user = UserService.get_user_by_username(username)
                    except NotFound:
                        current_app.logger.error(
                            f"Username {username} not found")
                        continue  # If we can't find the user, keep going no need to fail

                    message = Message()
                    message.message_type = MessageType.MENTION_NOTIFICATION.value
                    message.project_id = project_id
                    message.from_user_id = chat_from
                    message.to_user_id = user.id
                    message.subject = f"You were mentioned in {link} chat"
                    message.message = chat
                    messages.append(dict(message=message, user=user))

                MessageService._push_messages(messages)

            query = """ select user_id from project_favorites where project_id = :project_id"""
            favorited_users_results = db.engine.execute(text(query),
                                                        project_id=project_id)
            favorited_users = [r[0] for r in favorited_users_results]

            # Notify all contributors except the user that created the comment.
            contributed_users_results = (TaskHistory.query.with_entities(
                TaskHistory.user_id.distinct()
            ).filter(TaskHistory.project_id == project_id).filter(
                TaskHistory.user_id != chat_from).filter(
                    TaskHistory.action == TaskAction.STATE_CHANGE.name).all())
            contributed_users = [r[0] for r in contributed_users_results]

            users_to_notify = list(set(contributed_users + favorited_users))

            if len(users_to_notify) != 0:
                from_user = User.query.get(chat_from)
                from_user_link = MessageService.get_user_link(
                    from_user.username)
                project_link = MessageService.get_project_link(
                    project_id, include_chat_section=True)
                messages = []
                for user_id in users_to_notify:
                    try:
                        user = UserService.get_user_dto_by_id(user_id)
                    except NotFound:
                        continue  # If we can't find the user, keep going no need to fail
                    message = Message()
                    message.message_type = MessageType.PROJECT_CHAT_NOTIFICATION.value
                    message.project_id = project_id
                    message.from_user_id = chat_from
                    message.to_user_id = user.id
                    message.subject = (
                        f"{from_user_link} left a comment in {project_link}")
                    message.message = chat
                    messages.append(dict(message=message, user=user))

                # it's important to keep that line inside the if to avoid duplicated emails
                MessageService._push_messages(messages)