예제 #1
0
 def test_add_flow_chat_double_user(self):
     self.test.data.flow[0].type = "chat"
     self.test.data.user.append(api.User())
     self.test.data.user[1].uuid = 1234567
     run_method = controller.ProtocolMethods(self.test)
     result = json.loads(run_method.get_response())
     self.assertEqual(result["errors"]["code"], 200)
예제 #2
0
    def _authentification(self):
        """Performs authentification of registered client,
        with issuance of a unique hash number of connection session.
        During authentification password transmitted by client
        and password contained in server database are verified.

        """
        if self.__check_login(self.request.data.user[0].login) is False:
            self.__catching_error(404)
        else:
            dbquery = models.UserConfig.selectBy(
                login=self.request.data.user[0].login).getOne()
            generator = lib.Hash(password=self.request.data.user[0].password,
                                 uuid=dbquery.uuid,
                                 salt=dbquery.salt,
                                 key=dbquery.key,
                                 hash_password=dbquery.hashPassword)
            if generator.check_password():
                dbquery.authId = generator.auth_id()
                user = api.User()
                user.uuid = dbquery.uuid
                user.auth_id = dbquery.authId
                self.response.data.user.append(user)
                self.__catching_error(200)
            else:
                self.__catching_error(401)
예제 #3
0
    def _get_update(self):
        """The function displays messages of a specific flow,
        from the timestamp recorded in the request to the server timestamp,
        retrieves them from the database
        and issues them as an array consisting of JSON

        """
        # TODO внеести измнения в протокол, добавить фильтр
        # по дате создания пользователя
        dbquery_user = models.UserConfig.selectBy()
        dbquery_flow = models.Flow.select(
            models.Flow.q.timeCreated >= self.request.data.time)
        dbquery_message = models.Message.select(
            models.Message.q.time >= self.request.data.time)
        if dbquery_message.count():
            for element in dbquery_message:
                message = api.Message()
                message.text = element.text
                message.time = element.time
                message.emoji = element.emoji
                message.file_picture = element.filePicture
                message.file_video = element.fileVideo
                message.file_audio = element.fileAudio
                message.file_document = element.fileDocument
                message.from_user_uuid = element.userID
                message.from_flow_id = element.flowID
                message.edited_status = element.editedStatus
                self.response.data.message.append(message)
        elif dbquery_flow.count():
            for element in dbquery_flow:
                flow = api.Flow()
                flow.id = element.flowId
                flow.time = element.timeCreated
                flow.type = element.flowType
                flow.title = element.title
                flow.info = element.info
                self.response.data.flow.append(flow)
        elif dbquery_user.count():
            for element in dbquery_user:
                user = api.User()
                user.uuid = element.uuid
                user.username = element.username
                user.is_bot = element.isBot
                user.avatar = element.avatar
                user.bio = element.bio
                self.response.data.user.append(user)
        else:
            self.__catching_error(404)
        self.__catching_error(200)
예제 #4
0
    def _user_info(self):
        """Provides information about all personal settings of user.

        """
        try:
            dbquery = models.UserConfig.selectBy(
                uuid=self.request.data.user[0].uuid).getOne()
        except (SQLObjectIntegrityError, SQLObjectNotFound) as user_info_error:
            self.__catching_error(404, str(user_info_error))
        else:
            user = api.User()
            user.uuid = dbquery.uuid
            user.login = dbquery.login
            user.username = dbquery.username
            user.is_bot = dbquery.isBot
            user.email = dbquery.email
            user.avatar = dbquery.avatar
            user.bio = dbquery.bio
            self.response.data.user.append(user)
            self.__catching_error(200)
예제 #5
0
class ProtocolMethods:
    """The class is responsible for processing requests and forming answers
    according to "Udav" protocol. Protocol version and it's actual description:
    https://github.com/MoreliaTalk/morelia_protocol/blob/master/README.md
    """
    def __init__(self, request):
        self.response = api.ValidJSON()
        self.response.data = api.Data()
        self.response.data.flow = list()
        self.response.data.message = list()
        self.response.data.user = list()
        self.response.errors = api.Errors()
        self.response.jsonapi = api.Version()
        self.response.jsonapi.version = config.API_VERSION
        self.get_time = int(time())

        try:
            self.request = api.ValidJSON.parse_obj(request)
        except ValidationError as error:
            self.response.type = "errors"
            self.__catching_error(415, str(error))
        else:
            self.response.type = self.request.type
            if self.request.type == 'register_user':
                self._register_user()
            elif self.request.type == 'auth':
                self._authentification()
            else:
                if self.__check_auth_token(self.request.data.user[0].uuid,
                                           self.request.data.user[0].auth_id):
                    if self.request.type == 'send_message':
                        self._send_message()
                    elif self.request.type == 'all_flow':
                        self._all_flow()
                    elif self.request.type == 'add_flow':
                        self._add_flow()
                    elif self.request.type == 'all_messages':
                        self._all_messages()
                    elif self.request.type == 'delete_user':
                        self._delete_user()
                    elif self.request.type == 'delete_message':
                        self._delete_message()
                    elif self.request.type == 'edited_message':
                        self._edited_message()
                    elif self.request.type == "get_update":
                        self._get_update()
                    elif self.request.type == "ping-pong":
                        self._ping_pong()
                    elif self.request.type == 'user_info':
                        self._user_info()
                    else:
                        self._errors()
                else:
                    self.__catching_error(401)

    def get_response(self):
        """Function generates a JSON-object containing result
        of an instance of ProtocolMethod class.

        """
        return self.response.toJSON()

    def __check_auth_token(self, uuid: str, auth_id: str) -> bool:
        """Function checks uuid and auth_id of user

        Args:
            uuid (int, requires): Unique User ID
            auth_id (str, requires): authentification ID

        Returns:
            True if successful
            False if unsuccessful
        """
        try:
            dbquery = models.UserConfig.selectBy(uuid=uuid).getOne()
        except (dberrors.OperationalError, SQLObjectIntegrityError,
                SQLObjectNotFound):
            return False
        else:
            if auth_id == dbquery.authId:
                return True
            else:
                return False

    def __check_login(self, login: str) -> bool:
        """Provides information about all personal settings of user
        (in a server-friendly form)

        Args:
            login (str, optional): user login

        Returns:
            True if there is such a user
            False if no such user exists
        """
        try:
            models.UserConfig.selectBy(login=login).getOne()
        except (SQLObjectIntegrityError, SQLObjectNotFound):
            return False
        else:
            return True

    def __catching_error(self,
                         code: Union[int, str],
                         add_info: Optional[str] = None) -> None:
        """Function catches errors in the "try...except" content.
        Result is 'dict' with information about the code, status,
        time and detailed description of the error that has occurred.
        For errors like Exception and other unrecognized errors,
        code "520" and status "Unknown Error" are used.
        Function also automatically logs the error.

        Args:
            code (Union[int, str]): Error code or type and exception
            description.
            add_info (Optional[str], optional): Additional information
            to be added. The 'Exception' field is not used for exceptions.
            Defaults to None.

        Returns:
            dict: returns 'dict' according to the protocol,
                like: {
                    'code': 200,
                    'status': 'Ok',
                    'time': 123456545,
                    'detail': 'successfully'
                    }
        """
        if code in config.DICT_ERRORS:
            if add_info is None:
                add_info = config.DICT_ERRORS[code]['detail']
            self.response.errors.code = code
            self.response.errors.status = config.DICT_ERRORS[code]['status']
            self.response.errors.time = self.get_time
            self.response.errors.detail = add_info
        else:
            self.response.errors.code = 520
            self.response.errors.status = 'Unknown Error'
            self.response.errors.time = self.get_time
            self.response.errors.detail = code

    def _register_user(self):
        """The function registers the user who is not in the database.
        Note: This version also authentificate user, that exist in database
        Future version will return error if login exist in database

        """
        # FIXME после замены uuid на UUID из питоньего модуля
        random.seed(urandom(64))
        gen_uuid = random.randrange(10000, 999999999999)
        if self.__check_login(self.request.data.user[0].login):
            self.__catching_error(409)
        else:
            generated = lib.Hash(password=self.request.data.user[0].password,
                                 uuid=gen_uuid)
            models.UserConfig(uuid=gen_uuid,
                              password=self.request.data.user[0].password,
                              hashPassword=generated.password_hash(),
                              login=self.request.data.user[0].login,
                              username=self.request.data.user[0].username,
                              email=self.request.data.user[0].email,
                              key=generated.get_key(),
                              salt=generated.get_salt(),
                              authId=(gen_auth_id := generated.auth_id()))
            user = api.User()
            user.uuid = gen_uuid
            user.auth_id = gen_auth_id
            self.response.data.user.append(user)
            self.__catching_error(201)