From e164e74cde2868bffec2c841e0d626344f77c6cb Mon Sep 17 00:00:00 2001 From: vlados31 Date: Sun, 16 Oct 2022 13:31:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=20=D0=BE?= =?UTF-8?q?=D1=88=D0=B8=D0=B1=D0=BE=D0=BA=20API,=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D0=B1=D1=8F=D0=B7?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BD?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=D1=80=D0=B0=20=D1=82=D0=B5=D0=BB=D0=B5=D1=84?= =?UTF-8?q?=D0=BE=D0=BD=D0=B0=20=D0=BF=D1=80=D0=B8=20=D1=80=D0=B5=D0=B3?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/models.py | 2 +- api/api_errors.py | 49 +++++++++++++++++++++++++--------------------- api/api_methods.py | 46 +++++++++++++++++++++++++++++++++---------- api/api_utils.py | 5 ++++- api/models.py | 2 +- 5 files changed, 69 insertions(+), 35 deletions(-) diff --git a/account/models.py b/account/models.py index 8c6d522..478c0af 100644 --- a/account/models.py +++ b/account/models.py @@ -186,7 +186,7 @@ class SiteAccountManager(BaseUserManager): class SiteUser(AbstractBaseUser, PermissionsMixin): surname = models.CharField(max_length=60, verbose_name="Фамилия") name = models.CharField(max_length=60, verbose_name="Имя") - email = models.EmailField(unique=True, verbose_name="Email") + email = models.EmailField(unique=True, verbose_name="Email", null=True, blank=True, default=None) phone = models.CharField(unique=True, max_length=16, verbose_name="Телефон", validators=[ RegexValidator(regex="^\\+7[0-9]{10}$"), ]) diff --git a/api/api_errors.py b/api/api_errors.py index 40134cb..fc8226f 100644 --- a/api/api_errors.py +++ b/api/api_errors.py @@ -7,10 +7,10 @@ from arka.settings import PHONE_VERIFICATION_RESEND_TIME_SECS API_OK_OBJ = {"status": "success"} -API_ERROR_MULTIPLY_ERRORS = (None, 'multiply errors') - API_ERROR_INTERNAL_ERROR = (100, 'internal error') +API_ERROR_MULTIPLY_ERRORS = (101, 'multiply errors') + API_ERROR_METHOD_NOT_FOUND = (200, 'method not found') API_ERROR_MISSING_ARGUMENT = (201, 'missing argument') API_ERROR_UNKNOWN_ARGUMENT = (202, 'unknown argument') @@ -24,24 +24,25 @@ API_ERROR_INVALID_TOKEN = (503, 'invalid token') # времненное решение, позже нужно будет заменить на конкретные ошибки API_ERROR_USER_REGISTER = (510, 'user registration error') +API_ERROR_NEED_VERIFY = (511, 'need verification code') -API_ERROR_VALIDATION_INVALID_CODE = (520, 'invalid code') -API_ERROR_VALIDATION_MAX_ATTEMPTS = (521, 'max attempts') -API_ERROR_VALIDATION_CURRENTLY_VERIFIED = (522, 'currently phone is verified') -API_ERROR_VALIDATION_FAILED = (523, 'cannot be verified') -API_ERROR_VALIDATION_NOT_READY = (524, 'verification service not ready. call this method later') -API_ERROR_VALIDATION_NOT_FOUND = (525, 'verification service did not send code. call this method without \'code\'') -API_ERROR_VALIDATION_RESEND_LIMIT = (526, f'resend verification limit ' - f'(one verify for {PHONE_VERIFICATION_RESEND_TIME_SECS} secs)') -API_ERROR_VALIDATION_UNKNOWN = (527, 'unknown verification error') +API_ERROR_VERIFY_INVALID_CODE = (520, 'invalid code') +API_ERROR_VERIFY_MAX_ATTEMPTS = (521, 'max attempts') +API_ERROR_CURRENTLY_VERIFIED = (522, 'currently phone is verified') +API_ERROR_VERIFY_FAILED = (523, 'cannot be verified') +API_ERROR_VERIFY_NOT_READY = (524, 'verification service not ready. call this method later') +API_ERROR_VERIFY_NOT_FOUND = (525, 'verification service did not send code. call this method without \'code\'') +API_ERROR_VERIFY_RESEND_LIMIT = (526, f'resend verification limit ' + f'(one verify for {PHONE_VERIFICATION_RESEND_TIME_SECS} secs)') +API_ERROR_VERIFY_UNKNOWN = (527, 'unknown verification error') -API_ERROR_VALIDATION = { - PhoneVerificationService.CHECK_PHONE_INVALID_CODE: API_ERROR_VALIDATION_INVALID_CODE, - PhoneVerificationService.CHECK_PHONE_MAX_ATTEMPTS: API_ERROR_VALIDATION_MAX_ATTEMPTS, - PhoneVerificationService.CHECK_PHONE_FAILED: API_ERROR_VALIDATION_FAILED, - PhoneVerificationService.CHECK_PHONE_NOT_READY: API_ERROR_VALIDATION_NOT_READY, - PhoneVerificationService.CHECK_PHONE_NOT_FOUND: API_ERROR_VALIDATION_NOT_FOUND, - PhoneVerificationService.CHECK_PHONE_RESEND_LIMIT: API_ERROR_VALIDATION_RESEND_LIMIT, +API_ERROR_VERIFICATION = { + PhoneVerificationService.CHECK_PHONE_INVALID_CODE: API_ERROR_VERIFY_INVALID_CODE, + PhoneVerificationService.CHECK_PHONE_MAX_ATTEMPTS: API_ERROR_VERIFY_MAX_ATTEMPTS, + PhoneVerificationService.CHECK_PHONE_FAILED: API_ERROR_VERIFY_FAILED, + PhoneVerificationService.CHECK_PHONE_NOT_READY: API_ERROR_VERIFY_NOT_READY, + PhoneVerificationService.CHECK_PHONE_NOT_FOUND: API_ERROR_VERIFY_NOT_FOUND, + PhoneVerificationService.CHECK_PHONE_RESEND_LIMIT: API_ERROR_VERIFY_RESEND_LIMIT, } @@ -66,9 +67,13 @@ def make_error_object(ex: Exception | list): "status": "error" } if type(ex) == list: - data["error"] = [__make_error(e) for e in ex] + data["error"] = { + "code": API_ERROR_MULTIPLY_ERRORS[0], + "message": API_ERROR_MULTIPLY_ERRORS[1], + } + data["related"] = [__make_error(e) for e in ex] else: - data["error"] = [__make_error(ex)] + data["error"] = __make_error(ex) return data except BaseException as err: @@ -76,9 +81,9 @@ def make_error_object(ex: Exception | list): return { "status": "error", - "error": [{ + "error": { "code": API_ERROR_INTERNAL_ERROR[0], "message": API_ERROR_INTERNAL_ERROR[1], "related": f"Exception {type(err)}: {str(err)}" - }] + } } diff --git a/api/api_methods.py b/api/api_methods.py index 51cc9b0..cbbaeae 100644 --- a/api/api_methods.py +++ b/api/api_methods.py @@ -42,10 +42,12 @@ class ApiAccount: api_make_param("surname", str, "Фамилия пользователя"), api_make_param("phone", str, "Телефон в формате [[+]7]1112223333 " "(в квадратных скобках необязательная часть)"), - api_make_param("email", str, "Почта"), + api_make_param("email", str, "Почта", False), api_make_param("password", str, "Пароль пользователя"), + api_make_param("code", int, "Код верификации (требуется если клиенту будет отправлена " + "одна из ошибок верификации)", False), ], returns="Аналогично методу account.auth в случае успеха") - def register(name, surname, phone, email, password): + def register(name, surname, phone, email, password, code): user = SiteUser.create_user( name=name, @@ -57,7 +59,29 @@ class ApiAccount: try: user.full_clean() - user.save() + + # теперь проверяем телефон + if code is None: + res, err_code = PhoneVerificationService.send_verify(user.phone) + + if not res: + if err_code in API_ERROR_VERIFICATION: + raise Exception(API_ERROR_VERIFICATION[err_code]) + else: + raise Exception(API_ERROR_VERIFY_UNKNOWN) + + raise Exception(API_ERROR_NEED_VERIFY) + else: + res, err_code = PhoneVerificationService.check_code(user.phone, code) + + if res: + user.is_phone_verified = True + user.save() + else: + if err_code in API_ERROR_VERIFICATION: + raise Exception(API_ERROR_VERIFICATION[err_code]) + else: + raise Exception(API_ERROR_VERIFY_UNKNOWN) try: token = UserToken.create_token(user) @@ -81,6 +105,8 @@ class ApiAccount: }) errors[field_name] = obj raise Exception(API_ERROR_USER_REGISTER, errors) + except BaseException as ex: + raise ex @staticmethod @api_method("account.verifyPhone", @@ -95,16 +121,16 @@ class ApiAccount: user = access_token.user if user.is_phone_verified: - raise Exception(API_ERROR_VALIDATION_CURRENTLY_VERIFIED) + raise Exception(API_ERROR_CURRENTLY_VERIFIED) if code is None: res, err_code = PhoneVerificationService.send_verify(user.phone) if not res: - if err_code in API_ERROR_VALIDATION: - raise Exception(API_ERROR_VALIDATION[err_code]) + if err_code in API_ERROR_VERIFICATION: + raise Exception(API_ERROR_VERIFICATION[err_code]) else: - raise Exception(API_ERROR_VALIDATION_UNKNOWN) + raise Exception(API_ERROR_VERIFY_UNKNOWN) return api_make_response({"action": "phone_call"}) else: @@ -115,10 +141,10 @@ class ApiAccount: user.save() return api_make_response({}) else: - if err_code in API_ERROR_VALIDATION: - raise Exception(API_ERROR_VALIDATION[err_code]) + if err_code in API_ERROR_VERIFICATION: + raise Exception(API_ERROR_VERIFICATION[err_code]) else: - raise Exception(API_ERROR_VALIDATION_UNKNOWN) + raise Exception(API_ERROR_VERIFY_UNKNOWN) @staticmethod @api_method("account.get", diff --git a/api/api_utils.py b/api/api_utils.py index d27f244..61c2fbd 100644 --- a/api/api_utils.py +++ b/api/api_utils.py @@ -82,7 +82,10 @@ def api_method(func_name, doc="", params: list or None = None, returns=""): errors.append(ex) print(f"errors: {errors}, args: {func_args}") if len(errors) > 0: - return make_error_object(errors) + if len(errors) == 1: + return make_error_object(errors[0]) + else: + return make_error_object(errors) else: out = func(**func_args) if out is None: diff --git a/api/models.py b/api/models.py index f5c99a7..d735d07 100644 --- a/api/models.py +++ b/api/models.py @@ -61,7 +61,7 @@ class UserToken(models.Model): def save(self, *args, **kwargs): if len(self.access_token) == 0: - source = bytearray(self.user.email + self.user.password + str(datetime.now()), 'utf-8') + source = bytearray(str(self.user.email) + self.user.password + str(datetime.now()), 'utf-8') t = sha512(source).hexdigest() # чекаем токен в базе