Beispiel #1
0
 def set_user_offline(cls, user_data):
     user = Authenticator.authenticate(user_data)
     user.online = False
     UserDatabaseClient.update_user(user)
     DatabaseClient.commit()
     cls.logger().info(f"User #{user.id} set offline.")
     return SuccessfulUserResponse(user)
Beispiel #2
0
    def _login_app_user(cls, user_data):
        user = UserDatabaseClient.get_user_by_email(user_data.email)

        if user:
            try:
                if hashing.verify(user_data.password, user.password):
                    cls.logger().debug(f"Generating token for user {user.id}")
                    user.token = Authenticator.generate(
                        user.id, user_data.password)
                    user.online = True
                    UserDatabaseClient.update_user(user)
                    DatabaseClient.commit()
                    cls.logger().info(f"User #{user.id} logged in")
                    headers = {"auth_token": user.token}
                    return SuccessfulUserResponse(user, headers)
                else:
                    cls.logger().info(
                        f"Wrong credentials while attempting to log in user #{user_data.email}"
                    )
                    return SuccessfulUserMessageResponse(
                        "Wrong email or password.",
                        UserResponseStatus.WRONG_CREDENTIALS.value)
            except ValueError:
                cls.logger().info(
                    f"Wrong credentials while attempting to log in user #{user_data.email}"
                )
                return SuccessfulUserMessageResponse(
                    "Wrong email or password.",
                    UserResponseStatus.WRONG_CREDENTIALS.value)
        else:
            cls.logger().info(f"User #{user_data.email} not found.")
            raise UserNotFoundError("User not found.",
                                    UserResponseStatus.USER_NOT_FOUND.value)
Beispiel #3
0
 def logout_user(cls, user_data):
     user = Authenticator.authenticate(user_data)
     user.token = None
     user.online = False
     UserDatabaseClient.update_user(user)
     DatabaseClient.commit()
     cls.logger().info(f"User #{user.id} logged out.")
     return SuccessfulUserMessageResponse(
         "User logged out.", UserResponseStatus.LOGGED_OUT.value)
Beispiel #4
0
    def create_channel(cls, creation_data):
        user = Authenticator.authenticate_team(creation_data.authentication)

        try:
            new_client = UserDatabaseClient.add_client()
            new_channel = Channel(
                channel_id=new_client.id,
                team_id=user.team_id,
                creator=user.id,
                name=creation_data.name,
                visibility=creation_data.visibility,
                description=creation_data.description,
                welcome_message=creation_data.welcome_message
            )
            ChannelDatabaseClient.add_channel(new_channel)
            new_channel_user = ChannelUser(user_id=user.id, channel_id=new_channel.channel_id)
            ChannelDatabaseClient.add_channel_user(new_channel_user)
            new_chat = Chat(user_id=user.id, chat_id=new_channel.channel_id, team_id=new_channel.team_id)
            MessageDatabaseClient.add_chat(new_chat)
            DatabaseClient.commit()
            channel = ChannelDatabaseClient.get_channel_by_id(new_channel.channel_id)
            cls.logger().info(f"Channel #{new_channel.channel_id} created in team {new_channel.team_id}.")
            cls.logger().info(f"User #{user.id} assigned as channel #{new_channel.channel_id} creator.")
        except IntegrityError:
            DatabaseClient.rollback()
            if ChannelDatabaseClient.get_channel_by_name(creation_data.name) is not None:
                cls.logger().info(f"Failing to create channel {creation_data.name}. Name already in use.")
                return BadRequestChannelMessageResponse(f"Channel name {creation_data.name} already in use.",
                                                        TeamResponseStatus.ALREADY_REGISTERED.value)
            else:
                cls.logger().error(f"Failing to create channel {creation_data.name}.")
                return UnsuccessfulChannelMessageResponse("Couldn't create channel.")
        else:
            return SuccessfulChannelResponse(channel, TeamResponseStatus.CREATED.value)
    def notify_change_role(cls, user_team, old_role, admin_id):
        admin = UserDatabaseClient.get_user_by_id(admin_id)
        team = TeamDatabaseClient.get_team_by_id(user_team.team_id)
        new_role = user_team.role

        condition = "upgraded" if TeamRoles.is_higher_role(
            new_role, old_role) else "downgraded"
        message_body = f"You have been {condition} in team {team.name}!"
        data = {
            "notification_type": NotificationType.TEAM_ROLE_CHANGE.value,
            "team_name": team.name,
            "admin_id": admin.id
        }

        try:
            cls.logger().debug(
                f"Sending notification to topic {user_team.user_id}, with title \"{cls.APP_NAME}\" "
                f"and body \"{message_body}\"")
            response = cls.push_service.notify_topic_subscribers(
                topic_name=user_team.user_id,
                message_title=cls.APP_NAME,
                message_body=message_body,
                data_message=data)

            failures = response.get("failure")
            if failures > 0:
                cls.logger().error(
                    f"There's been detected {failures} failures sending user #{user_team.user_id} new "
                    f"role notifications to Firebase.")
            else:
                cls.logger().info(
                    f"New role notified to user #{user_team.user_id}.")

        except ConnectionError:
            cls.logger().error("Couldn't connect to Firebase server.")
Beispiel #6
0
    def create_bot(cls, bot_data):
        admin = Authenticator.authenticate_team(bot_data.authentication, UserRoles.is_admin)

        try:
            new_client = UserDatabaseClient.add_client()
            new_bot = Bot(
                bot_id=new_client.id,
                name=bot_data.name,
                callback=bot_data.callback,
                token=Authenticator.generate(new_client.id)
            )
            BotDatabaseClient.add_bot(new_bot)
            team_bot = TeamUser(
                user_id=new_client.id,
                team_id=admin.team_id,
                role=TeamRoles.BOT.value
            )
            TeamDatabaseClient.add_team_user(team_bot)
            DatabaseClient.commit()
            cls.logger().info(f"Bot #{new_bot.id} created in team {admin.team_id} with callback url {new_bot.callback} "
                              f"by admin {admin.id}.")
            return SuccessfulUserMessageResponse("Bot created.", UserResponseStatus.OK.value)

        except IntegrityError as exc:
            DatabaseClient.rollback()
            if BotDatabaseClient.get_bot_by_name(bot_data.name) is not None:
                cls.logger().info(f"Failing to create bot {bot_data.name}. Name already in use.", exc)
                return BadRequestUserMessageResponse("Name already in use for other bot.",
                                                     UserResponseStatus.ALREADY_REGISTERED.value)
            else:
                cls.logger().info(f"Failing to create bot {bot_data.name}.")
                return UnsuccessfulClientResponse("Couldn't create bot.")
Beispiel #7
0
    def create_user(cls, user_data):
        if UserDatabaseClient.get_user_by_username(
                user_data.username) is not None:
            cls.logger().info(
                f"Failing to create user #{user_data.username}. Username already in use."
            )
            return BadRequestUserMessageResponse(
                "Username already in use for other user.",
                UserResponseStatus.ALREADY_REGISTERED.value)
        try:
            new_client = UserDatabaseClient.add_client()
            new_user = User(user_id=new_client.id,
                            username=user_data.username,
                            email=user_data.email,
                            password=hashing.hash(user_data.password),
                            first_name=user_data.first_name,
                            last_name=user_data.last_name,
                            profile_pic=user_data.profile_pic,
                            role=user_data.role or UserRoles.USER.value,
                            token=Authenticator.generate(
                                new_client.id, user_data.password))
            UserDatabaseClient.add_user(new_user)
            DatabaseClient.commit()
            cls.logger().info(f"User #{new_client.id} created.")
            headers = {"auth_token": new_user.token}
            return SuccessfulUserResponse(new_user, headers)

        except IntegrityError as exc:
            DatabaseClient.rollback()
            if UserDatabaseClient.get_user_by_email(
                    user_data.email) is not None:
                cls.logger().info(
                    f"Failing to create user {user_data.username}. Email already in use.",
                    exc)
                return BadRequestUserMessageResponse(
                    "Email already in use for other user.",
                    UserResponseStatus.ALREADY_REGISTERED.value)
            else:
                cls.logger().info(
                    f"Failing to create user #{user_data.username}.")
                return UnsuccessfulClientResponse("Couldn't create user.")
        except:
            DatabaseClient.rollback()
            cls.logger().info(f"Failing to create user #{user_data.username}.")
            return UnsuccessfulClientResponse("Couldn't create user.")
Beispiel #8
0
    def update_user(cls, update_data):
        user = Authenticator.authenticate(update_data)

        user.username = \
            update_data.updated_user["username"] if "username" in update_data.updated_user else user.username
        user.email = \
            update_data.updated_user["email"] if "email" in update_data.updated_user else user.email
        user.password = \
            hashing.hash(
                update_data.updated_user["password"]) if "password" in update_data.updated_user else user.password
        user.first_name = \
            update_data.updated_user["first_name"] if "first_name" in update_data.updated_user else user.first_name
        user.last_name = \
            update_data.updated_user["last_name"] if "last_name" in update_data.updated_user else user.last_name
        user.profile_pic = \
            update_data.updated_user["profile_pic"] if "profile_pic" in update_data.updated_user else user.profile_pic

        try:
            UserDatabaseClient.update_user(user)
            DatabaseClient.commit()
            cls.logger().info(f"User {user.id} information updated.")
            return SuccessfulUserResponse(user)
        except IntegrityError:
            DatabaseClient.rollback()
            new_username = update_data.updated_user.get("username")
            new_email = update_data.updated_user.get("email")

            if UserDatabaseClient.get_user_by_username(
                    new_username) is not None:
                cls.logger().info(
                    f"Name {new_email} is taken for another user.")
                return BadRequestUserMessageResponse(
                    f"Name {new_username} is already in use!",
                    UserResponseStatus.ALREADY_REGISTERED.value)
            elif UserDatabaseClient.get_user_by_email(new_email) is not None:
                cls.logger().info(
                    f"Email {new_email} is taken for another user.")
                return BadRequestUserMessageResponse(
                    f"Email {new_email} is already in use!",
                    UserResponseStatus.ALREADY_REGISTERED.value)
            else:
                cls.logger().error(
                    f"Couldn't update user {user.id} information.")
                return UnsuccessfulClientResponse(
                    "Couldn't update user information!")
Beispiel #9
0
    def add_user(cls, add_data):
        admin = Authenticator.authenticate(add_data.authentication,
                                           UserRoles.is_admin)
        user = UserDatabaseClient.get_user_by_id(add_data.add_user_id)

        if user is None:
            cls.logger().info(f"User {add_data.add_user_id} not found.")
            raise UserNotFoundError("User not found.",
                                    UserResponseStatus.USER_NOT_FOUND.value)

        if user.role == UserRoles.ADMIN.value:
            cls.logger().warning(
                f"Admin #{admin.id} trying to add other admin to a team.")
            return BadRequestTeamMessageResponse(
                "You cannot add an admin to a team!",
                TeamResponseStatus.ROLE_UNAVAILABLE.value)

        if TeamDatabaseClient.get_user_in_team_by_ids(
                user.id, add_data.authentication.team_id) is not None:
            cls.logger().info(
                f"User {add_data.add_user_id} already part of team #{add_data.authentication.team_id}."
            )
            return BadRequestTeamMessageResponse(
                "This user already belongs to the team.",
                TeamResponseStatus.ALREADY_REGISTERED.value)

        previous_invitation = TeamDatabaseClient.get_team_invite(
            add_data.authentication.team_id, user.email)

        if previous_invitation is not None:
            cls.logger().info(
                f"Deleting old invitation for user {add_data.add_user_id} to team "
                f"#{add_data.authentication.team_id}.")
            TeamDatabaseClient.delete_invite(previous_invitation)
            DatabaseClient.commit()

        added_user = TeamUser(user_id=add_data.add_user_id,
                              team_id=add_data.authentication.team_id)

        try:
            TeamDatabaseClient.add_team_user(added_user)
            DatabaseClient.commit()
            BotService.tito_welcome(added_user.user_id, added_user.team_id)
            cls.logger().info(
                f"Added user #{added_user.user_id} to team #{added_user.team_id} by admin #{admin.id}."
            )
            return SuccessfulTeamMessageResponse(
                "User added.", TeamResponseStatus.ADDED.value)

        except IntegrityError:
            DatabaseClient.rollback()
            cls.logger().error(
                f"Couldn't add user #{added_user.user_id} to team #{added_user.team_id}."
            )
            return UnsuccessfulTeamMessageResponse(
                "Couldn't invite user to team.")
Beispiel #10
0
    def team_user_profile(cls, user_id, team_id, admin_search=False):
        profile = UserDatabaseClient.get_user_profile(user_id)
        cls.logger().info(f"Retrieved user #{user_id} profile.")
        output_profile = cls._generate_user_profile(profile)

        if admin_search or any(
                list(
                    map(lambda team: team.get("id") == team_id,
                        output_profile.get("teams")))):
            return SuccessfulFullUserResponse(output_profile)
    def notify_team_invitation(cls, invitation, inviter_id):
        inviter_user = UserDatabaseClient.get_user_by_id(inviter_id)
        invited_user = UserDatabaseClient.get_user_by_email(invitation.email)
        team = TeamDatabaseClient.get_team_by_id(invitation.team_id)

        if invited_user is not None:
            message_body = "You have been invited to join a team!"
            data = {
                "notification_type": NotificationType.TEAM_INVITATION.value,
                "team_name": team.name,
                "inviter_id": inviter_user.id,
                "invitation_token": invitation.token
            }

            try:
                cls.logger().debug(
                    f"Sending notification to topic {invited_user.id}, with title \"{cls.APP_NAME}\" "
                    f"and body \"{message_body}\"")
                response = cls.push_service.notify_topic_subscribers(
                    topic_name=invited_user.id,
                    message_title=cls.APP_NAME,
                    message_body=message_body,
                    data_message=data)

                failures = response.get("failure")
                if failures > 0:
                    cls.logger().error(
                        f"There's been detected {failures} failures sending user #{invited_user.id}'s "
                        f"team invite notification to Firebase.")
                else:
                    cls.logger().info(
                        f"Team invite notified to user #{invited_user.id}.")

            except ConnectionError:
                cls.logger().error("Couldn't connect to Firebase server.")

        else:
            cls.logger().info(
                f"The invited user is not already registered so it cannot receive a notification."
            )
Beispiel #12
0
    def send_message(cls, inbox_data):
        user = Authenticator.authenticate_team(inbox_data.authentication)

        if user.id == inbox_data.chat_id:
            raise WrongActionError("You cannot send a message to yourself!", MessageResponseStatus.ERROR.value)

        receiver = cls._determinate_message_receiver(inbox_data.chat_id, user.team_id)
        if receiver is None or receiver.team_id != user.team_id:
            cls.logger().info(f"Trying to send a message to client #{inbox_data.chat_id} who's not part of team "
                              f"{user.team_id}.")
            return BadRequestMessageSentResponse("The receiver it's not part of this team!",
                                                 TeamResponseStatus.USER_NOT_MEMBER.value)

        new_message = Message(
            sender_id=user.id,
            receiver_id=inbox_data.chat_id,
            team_id=user.team_id,
            content=inbox_data.content,
            send_type=SendMessageType.DIRECT.value if receiver.is_user else SendMessageType.CHANNEL.value,
            message_type=inbox_data.message_type
        )

        chat_sender, chat_receivers = cls._increase_chats_offset(user.id, inbox_data.chat_id, user.team_id, receiver.is_user)

        try:
            new_message = MessageDatabaseClient.add_message(new_message)
            if inbox_data.mentions is not None:
                MentionService.save_mentions(new_message, inbox_data.mentions)
            MessageDatabaseClient.add_or_update_chat(chat_sender)
            for chat_receiver in chat_receivers:
                MessageDatabaseClient.add_or_update_chat(chat_receiver)
            DatabaseClient.commit()
            NotificationService.notify_message(new_message, receiver.is_user)
            cls.logger().info(f"Message sent from user #{new_message.sender_id} to client #{new_message.receiver_id}.")
        except IntegrityError:
            DatabaseClient.rollback()
            if UserDatabaseClient.get_client_by_id(inbox_data.chat_id) is None:
                cls.logger().error(f"User #{new_message.sender_id} trying to sent a message to an nonexistent user.")
                raise UserNotFoundError("User not found.", UserResponseStatus.USER_NOT_FOUND.value)
            else:
                cls.logger().error(f"Failing to send message from user #{new_message.sender_id} to client"
                                   f" #{inbox_data.chat_id}.")
                return UnsuccessfulMessageSentResponse("Couldn't sent message.")
        except FlushError:
            cls.logger().error(
                f"Failing to send message from user #{new_message.sender_id} to client #{inbox_data.chat_id} "
                f"due to DB problems.")
            return UnsuccessfulMessageSentResponse("Couldn't sent message.")
        else:
            return SuccessfulMessageSentResponse("Message sent")
Beispiel #13
0
    def recover_password(cls, recover_data):
        user = UserDatabaseClient.get_user_by_email(recover_data.email)

        if user is not None:
            old_password_recovery = UserDatabaseClient.get_password_recovery_by_id(
                user.id)

            if old_password_recovery is not None:
                cls.logger().debug(
                    f"It already exists a recovery token for user {user.username}. Resending token."
                )
                recovery_token = old_password_recovery.token

            else:
                recovery_token = Authenticator.generate_recovery_token()
                cls.logger().debug("Generating recovery token")
                password_recovery = PasswordRecovery(user_id=user.id,
                                                     token=recovery_token)
                UserDatabaseClient.add_password_recovery(password_recovery)
                DatabaseClient.commit()

            email_data = RecoveryPasswordEmailDTO(
                email=user.email,
                username=user.username,
                token=recovery_token,
                message_template=EmailService.recovery_token_message)
            EmailService.send_email(email_data)

            cls.logger().info(
                f"Sending recovery token email for user {user.username}.")
            return SuccessfulUserMessageResponse("Recovery token sent!",
                                                 UserResponseStatus.OK.value)

        else:
            cls.logger().info(f"User {recover_data.email} not found.")
            raise UserNotFoundError("User not found.",
                                    UserResponseStatus.USER_NOT_FOUND.value)
    def authenticate(cls, authentication, role_verifying=lambda _: True):
        logger = logging.getLogger(cls.__name__)

        try:
            payload = jwt.decode(authentication.token.encode(),
                                 cls._secret,
                                 algorithms='HS256')

            user = UserDatabaseClient.get_user_by_id(payload.get("user_id"))

            if user is not None:
                if role_verifying(user.role):
                    if user.token == authentication.token:
                        logger.info(f"User #{user.id} authenticated.")
                        return user
                    else:
                        logger.info(
                            f"Failing to authenticate user #{payload['user_id']}."
                        )
                        raise WrongTokenError(
                            "You must be logged to perform this action.",
                            UserResponseStatus.WRONG_TOKEN.value)
                else:
                    logger.info(
                        f"User #{user.id} does not have permissions to perform this action."
                    )
                    raise NoPermissionsError(
                        "You don't have enough permissions to perform this action.",
                        TeamResponseStatus.NOT_ENOUGH_PERMISSIONS.value)
            else:
                bot = BotDatabaseClient.get_bot_by_id(payload.get("user_id"))

                if bot is not None:
                    logger.info(f"Bot #{bot.id} authenticated.")
                    return bot
                else:
                    logger.info(f"User not found.")
                    raise UserNotFoundError(
                        "User not found.",
                        UserResponseStatus.USER_NOT_FOUND.value)

        except DecodeError:
            logger.info(f"Failing to authenticate user.")
            raise WrongTokenError("You must be logged to perform this action.",
                                  UserResponseStatus.WRONG_TOKEN.value)
    def authenticate_channel(cls,
                             authentication,
                             channel_role_verifying=lambda _: True):
        logger = logging.getLogger(cls.__name__)

        try:
            user = cls.authenticate_team(
                authentication, lambda user: TeamRoles.is_team_moderator(user))
            user.channel_id = authentication.channel_id
            user.is_channel_creator = False
            return user
        except NoPermissionsError:

            user = cls.authenticate_team(authentication)
            channel_user = UserDatabaseClient.get_channel_user_by_ids(
                user.id, authentication.channel_id)

            if channel_user is not None:
                if channel_role_verifying(channel_user.is_channel_creator):
                    logger.info(
                        f"User {user.username} authenticated as channel #{authentication.channel_id} creator."
                    )
                    return channel_user
                else:
                    raise NoPermissionsError(
                        "You don't have enough permissions to perform this action.",
                        TeamResponseStatus.NOT_ENOUGH_PERMISSIONS.value)
            else:
                channel = ChannelDatabaseClient.get_channel_by_id(
                    authentication.channel_id)

                if channel is None:
                    logger.info(
                        f"Chanel #{authentication.channel_id} not found.")
                    raise ChannelNotFoundError(
                        "Channel not found.",
                        ChannelResponseStatus.CHANNEL_NOT_FOUND.value)
                else:
                    logger.info(
                        f"User {user.username} trying to access channel #{channel.channel_id}, "
                        f"when it's not part of it.")
                    raise NoPermissionsError(
                        "You're not part of this channel!",
                        TeamResponseStatus.NOT_ENOUGH_PERMISSIONS.value)
    def notify_mention(cls, message, mentioned_id):
        is_not_bot = BotDatabaseClient.get_bot_by_id(mentioned_id) is None

        if is_not_bot:
            team = TeamDatabaseClient.get_team_by_id(message.team_id)
            sender = UserDatabaseClient.get_user_by_id(message.sender_id)

            if sender is None:
                sender = BotDatabaseClient.get_bot_by_id(message.sender_id)

            message_body = "You have been mentioned!"
            data = {
                "notification_type": NotificationType.MENTION.value,
                "team_name": team.name,
                "sender_id": sender.id
            }

            channel = ChannelDatabaseClient.get_channel_by_id(mentioned_id)
            if channel is not None:
                data["channel_name"] = channel.name

            try:
                cls.logger().debug(
                    f"Sending notification to topic {mentioned_id}, with title \"{cls.APP_NAME}\" "
                    f"and body \"{message_body}\"")
                response = cls.push_service.notify_topic_subscribers(
                    topic_name=mentioned_id,
                    message_title=cls.APP_NAME,
                    message_body=message_body,
                    data_message=data)

                failures = response.get("failure")
                if failures > 0:
                    cls.logger().error(
                        f"There's been detected {failures} failures sending the mentions notification for "
                        f"receiver #{message.receiver_id} to Firebase.")
                else:
                    cls.logger().info(
                        f"New mention notified to receiver #{message.receiver_id}."
                    )
            except ConnectionError:
                cls.logger().error("Couldn't connect to Firebase server.")
    def authenticate_team(cls, authentication, role_verifying=lambda _: True):
        logger = logging.getLogger(cls.__name__)

        user = cls.authenticate(authentication)

        if user.role == UserRoles.ADMIN.value:
            user.user_role = user.role
            user.team_id = authentication.team_id
            user.team_role = user.role
            return user

        team_user = UserDatabaseClient.get_team_user_by_ids(
            user.id, authentication.team_id)

        if team_user is not None:
            if role_verifying(team_user.team_role):
                logger.info(
                    f"Client #{team_user.id} authenticated as team #{team_user.team_id} {team_user.team_role}."
                )
                return team_user
            else:
                logger.info(
                    f"User #{user.id} does not have permissions to perform this action."
                )
                raise NoPermissionsError(
                    "You don't have enough permissions to perform this action.",
                    TeamResponseStatus.NOT_ENOUGH_PERMISSIONS.value)
        else:
            team = TeamDatabaseClient.get_team_by_id(authentication.team_id)

            if team is None:
                logger.info(f"Team #{authentication.team_id} not found.")
                raise TeamNotFoundError("Team not found.",
                                        TeamResponseStatus.NOT_FOUND.value)
            else:
                logger.info(
                    f"Client #{user.id} trying to access team #{team.id}, when it's not part of it."
                )
                raise NoPermissionsError(
                    "You're not part of this team!",
                    TeamResponseStatus.NOT_ENOUGH_PERMISSIONS.value)
Beispiel #18
0
    def add_member(cls, invitation_data):
        user = Authenticator.authenticate_channel(invitation_data.authentication, TeamRoles.is_channel_creator)

        invited_user = UserDatabaseClient.get_user_by_id(invitation_data.user_invited_id)
        if invited_user is None:
            cls.logger().info(f"Trying to add user an nonexistent user to channel #{user.channel_id}.")
            return BadRequestChannelMessageResponse("Invited user not found!", UserResponseStatus.USER_NOT_FOUND.value)

        invited_user_in_team = TeamDatabaseClient.get_user_in_team_by_ids(invited_user.id, user.team_id)
        if invited_user_in_team is None:
            cls.logger().info(f"Trying to add user {invited_user.id} to channel #{user.channel_id}, but it's not part "
                              f"of the team #{user.team_id}.")
            return BadRequestChannelMessageResponse("User not part of the team!",
                                                    TeamResponseStatus.USER_NOT_MEMBER.value)

        try:
            new_channel_user = ChannelUser(user_id=invited_user.id, channel_id=user.channel_id)
            ChannelDatabaseClient.add_channel_user(new_channel_user)
            new_chat = Chat(user_id=invited_user.id, chat_id=user.channel_id, team_id=user.team_id)
            MessageDatabaseClient.add_chat(new_chat)
            DatabaseClient.commit()
            NotificationService.notify_channel_invitation(new_channel_user, user.id)
            cls.logger().info(f"User #{invited_user.id} added to channel #{user.channel_id} by {user.username}.")

        except IntegrityError:
            DatabaseClient.rollback()
            already_member = ChannelDatabaseClient.get_user_in_channel_by_ids(invited_user.id, user.channel_id)

            if already_member is not None:
                cls.logger().info(f"Failing to add user #{invited_user.id} to channel #{user.channel_id}. "
                                  f"The user is already part of it.")
                return BadRequestChannelMessageResponse(f"User already registered in channel.",
                                                        TeamResponseStatus.ALREADY_REGISTERED.value)
            else:
                cls.logger().error(f"Failing to add user #{invitation_data.user_invited_id} to channel"
                                   f"{invitation_data.authentication.channel_id}.")
                return UnsuccessfulChannelMessageResponse("Couldn't add user to channel.")
        else:
            return SuccessfulChannelMessageResponse("User added!", ChannelResponseStatus.ADDED.value)
    def notify_channel_invitation(cls, user_channel, inviter_id):
        inviter_user = UserDatabaseClient.get_user_by_id(inviter_id)
        channel = ChannelDatabaseClient.get_channel_by_id(
            user_channel.channel_id)
        team = TeamDatabaseClient.get_team_by_id(channel.team_id)

        message_body = f"You have been added to channel {channel.name} in team {team.name}!"
        data = {
            "notification_type": NotificationType.CHANNEL_INVITATION.value,
            "channel_name": channel.name,
            "team_name": team.name,
            "inviter_id": inviter_user.id
        }

        try:
            cls.logger().debug(
                f"Sending notification to topic {user_channel.user_id}, with title \"{cls.APP_NAME}\" "
                f"and body \"{message_body}\"")
            response = cls.push_service.notify_topic_subscribers(
                topic_name=user_channel.user_id,
                message_title=cls.APP_NAME,
                message_body=message_body,
                data_message=data)

            failures = response.get("failure")
            if failures > 0:
                cls.logger().error(
                    f"There's been detected {failures} failures sending user #{user_channel.user_id}'s "
                    f"channel invite notification to Firebase.")
            else:
                cls.logger().info(
                    f"Channel invitation notified to user #{user_channel.user_id}."
                )

        except ConnectionError:
            cls.logger().error("Couldn't connect to Firebase server.")
Beispiel #20
0
    def _login_facebook_user(cls, user_data):
        try:
            facebook_user = FacebookService.get_user_from_facebook(user_data)
            user = UserDatabaseClient.get_user_by_facebook_id(
                facebook_user.facebook_id)

            if user is not None:
                cls.logger().info(
                    f"Logging in Facebook user with Facebook ID #{facebook_user.facebook_id}."
                )
                cls.logger().debug(f"Generating token for user {user.id}")
                user.token = Authenticator.generate(user.id)
                user.online = True
                UserDatabaseClient.update_user(user)
                DatabaseClient.commit()
                cls.logger().info(f"User #{user.id} logged in.")
                headers = {"auth_token": user.token}
                return SuccessfulUserResponse(user, headers)
            else:
                cls.logger().info(
                    f"Creating new Facebook user with Facebook ID #{facebook_user.facebook_id}."
                )
                new_client = UserDatabaseClient.add_client()
                new_user = User(user_id=new_client.id,
                                facebook_id=facebook_user.facebook_id,
                                username=facebook_user.username,
                                email=facebook_user.email,
                                first_name=facebook_user.first_name,
                                last_name=facebook_user.last_name,
                                profile_pic=facebook_user.profile_pic,
                                role=UserRoles.USER.value,
                                token=Authenticator.generate(new_client.id))
                UserDatabaseClient.add_user(new_user)
                DatabaseClient.commit()
                cls.logger().info(f"User #{new_client.id} logged in.")
                headers = {"auth_token": new_user.token}
                return SuccessfulUserResponse(new_user, headers)
        except FacebookWrongTokenError:
            cls.logger().info(
                f"Failing to logging in user with Facebook token #{user_data.facebook_token}."
            )
            return UnsuccessfulClientResponse("Couldn't perform login.")
Beispiel #21
0
    def regenerate_token(cls, regenerate_data):
        user = UserDatabaseClient.get_user_by_email(regenerate_data.email)

        if user:
            password_recovery = UserDatabaseClient.get_password_recovery_by_id(
                user.id)

            if password_recovery:
                try:
                    UserDatabaseClient.delete_password_recovery(
                        password_recovery)
                    cls.logger().debug(
                        f"Deleting token recover entry for user {user.id}")
                    user.token = Authenticator.generate(user.id)
                    cls.logger().debug(
                        f"Regenerating token for user {user.id}")
                    user.online = True
                    UserDatabaseClient.update_user(user)
                    DatabaseClient.commit()
                    cls.logger().info(f"Logging in user {user.id}")
                    headers = {"auth_token": user.token}
                    return SuccessfulUserResponse(user, headers)
                except IntegrityError:
                    DatabaseClient.rollback()
                    cls.logger().error(
                        f"Couldn't regenerate token for user #{user.id}.")
                    return UnsuccessfulClientResponse(
                        "Couldn't regenerate token.")
            else:
                cls.logger().info(
                    f"Attempting to recover password for user #{user.id} with no password recovery token."
                )
                return BadRequestUserMessageResponse(
                    "You haven't ask for password recovery!",
                    UserResponseStatus.WRONG_CREDENTIALS.value)
        else:
            cls.logger().info(f"User {regenerate_data.email} not found.")
            raise UserNotFoundError("User not found.",
                                    UserResponseStatus.USER_NOT_FOUND.value)
Beispiel #22
0
 def user_profile(cls, user_data):
     user = Authenticator.authenticate(user_data)
     profile = UserDatabaseClient.get_user_profile(user.id)
     cls.logger().info(f"Retrieved user #{user.id} profile.")
     return SuccessfulFullUserResponse(cls._generate_user_profile(profile))
Beispiel #23
0
 def get_all_users(cls, user_data):
     admin = Authenticator.authenticate(user_data, UserRoles.is_admin)
     users = UserDatabaseClient.get_all_users()
     cls.logger().info(f"Admin {admin.id} retrieved {len(users)} users.")
     return SuccessfulUsersListResponse(
         list(map(lambda user: user.__dict__, users)))
Beispiel #24
0
    def invite_user(cls, invite_data):
        team_mod = Authenticator.authenticate_team(invite_data.authentication,
                                                   TeamRoles.is_team_moderator)

        invited_user = UserDatabaseClient.get_user_by_email(invite_data.email)
        if invited_user is not None and invited_user.role == UserRoles.ADMIN.value:
            cls.logger().info(
                f"Mod #{team_mod.id} tried to invite admin #{invited_user.id} to team #{team_mod.team_id}."
            )
            return BadRequestTeamMessageResponse(
                "You cannot invite an admin to a team!",
                TeamResponseStatus.ROLE_UNAVAILABLE.value)

        already_member = TeamDatabaseClient.get_user_in_team_by_email(
            invite_data.email, team_mod.team_id)
        if already_member is not None:
            cls.logger().info(
                f"Mod #{team_mod.id} tried to invite user #{already_member.user_id} to team "
                f"#{team_mod.team_id}, but it already belongs to that team.")
            return BadRequestTeamMessageResponse(
                "This user already belongs to the team.",
                TeamResponseStatus.ALREADY_REGISTERED.value)

        if TeamDatabaseClient.get_team_invite(team_mod.team_id,
                                              invite_data.email) is not None:
            cls.logger().info(
                f"Mod #{team_mod.id} tried to invite an user already invited to team #{team_mod.team_id}"
            )
            return BadRequestTeamMessageResponse(
                "This user was already invited to join the team.",
                TeamResponseStatus.ALREADY_INVITED.value)

        invite_token = Authenticator.generate_team_invitation()
        new_invite = TeamInvite(team_id=team_mod.team_id,
                                email=invite_data.email,
                                token=invite_token)

        try:
            TeamDatabaseClient.add_invite(new_invite)
            team = TeamDatabaseClient.get_team_by_id(team_mod.team_id)
            DatabaseClient.commit()
            cls.logger().info(
                f"New invitation for {new_invite.email} to join team #{team_mod.team_id}, by user #"
                f"{team_mod.id}.")

            email_data = TeamInvitationEmailDTO(
                email=invite_data.email,
                team_name=team.name,
                inviter_name=team_mod.username,
                token=invite_token,
                message_template=EmailService.team_invitation_message)
            EmailService.send_email(email_data)
            NotificationService.notify_team_invitation(new_invite, team_mod.id)
            cls.logger().info(
                f"Team #{team_mod.team_id} invitation email sent to {new_invite.email}."
            )

        except IntegrityError:
            DatabaseClient.rollback()
            cls.logger().error(
                f"Couldn't invite user {new_invite.email} to team #{team_mod.team_id}."
            )
            return UnsuccessfulTeamMessageResponse(
                "Couldn't invite user to team.")
        else:
            return SuccessfulTeamMessageResponse(
                "User invited.", TeamResponseStatus.INVITED.value)