Example #1
0
def api(title, version):
    log = Log.get('api')

    middlewares = [Negotiation_Middleware()]

    if Arg_Reader.db.auth:
        log.notice('JWT authentication enabled')
        middlewares.append(
            Falcon_Auth_Middleware(
                JWT_Auth_Backend(
                    user_loader=lambda token: {'user': token},
                    secret_key=Arg_Reader.db.auth_secret_key,
                    auth_header_prefix=Arg_Reader.db.auth_header_prefix),
                exempt_routes=['/api/doc', '/api/doc/swagger.json']))
    else:
        log.notice('JWT authentication disabled')

    if Arg_Reader.db.https:
        log.notice('Force to use HTTPS instead of HTTP')
        middlewares.append(RequireHTTPS())
    else:
        log.notice('HTTPS not set')

    if Arg_Reader.db.apm_enabled:
        log.notice('Elastic APM enabled')
        middlewares.append(
            Elastic_Apm_Middleware(service_name='lcp-apm',
                                   server_url=Arg_Reader.db.apm_server))
    else:
        log.notice('Elastic APM disabled')

    instance = API(middleware=middlewares)

    media_handlers = {
        falcon.MEDIA_JSON:
        JSON_Handler(loads=loads,
                     dumps=partial(dumps, ensure_ascii=False, sort_keys=True)),
        falcon.MEDIA_MSGPACK:
        Message_Pack_Handler(),
        falcon.MEDIA_XML:
        XML_Handler(),
        falcon.MEDIA_YAML:
        YAML_Handler()
    }
    instance.req_options.media_handlers.update(media_handlers)
    instance.resp_options.media_handlers.update(media_handlers)

    instance.add_error_handler(*Bad_Request_Handler.get())
    instance.add_error_handler(*Internal_Server_Error_Handler.get())
    instance.add_error_handler(*Unsupported_Media_Type_Handler.get())

    api_spec = Spec(api=instance, title=title, version=version)
    routes(api=instance, spec=api_spec.get())
    falcon_api_doc(instance,
                   config_path='./swagger/schema.json',
                   url_prefix='/api/doc',
                   title='API doc')
    api_spec.write()

    return instance
Example #2
0
class ResendEmailConfirm(ApiView):
    '''
    Re-send user email confirmation
    '''
    spec = Spec(
        Method.POST,
        s.Object(email=s.String()),
        Response(202),
    )

    def handle(self, data):
        email = data['email'].lower()
        user = User.objects.filter(
            is_active=True).filter(Q(email=email)
                                   | Q(new_email=email)).first()
        if user:
            if (email == user.email and user.email_confirm_code):
                signals.user_email_confirm.send(User, user=user, email=email)

            if (email == user.new_email and user.new_email_confirm_code):
                signals.user_new_email_confirm.send(User,
                                                    user=user,
                                                    email=email)

        return 202
Example #3
0
class GetMethod(ApiView):
    """sample view doc"""

    spec = Spec(Method.GET, s.Empty, Response(204, description='okay'))

    def handle(self, data):
        return 204
Example #4
0
class Signin(ApiView):
    '''
    User signin
    '''
    spec = Spec(
        Method.POST,
        s.Object(
            email=s.String(),
            password=s.String(),
        ),
        Response(200, schema=UserDef),
        Response(400, schema=Errors),
        Response(423),
    )

    def handle(self, data):
        user = authenticate(username=data['email'], password=data['password'])

        if user and user.is_active and user.email_confirmed:
            login(self.request, user)
            return {
                'id': user.pk,
                'email': user.email,
                'first_name': user.first_name,
                'short_name': user.get_short_name(),
            }

        if user and (not user.email_confirmed or not user.is_active):
            return 423

        return 400, {'errors': ['Email and/or password not recognized']}
Example #5
0
class SchemaView(ApiView):
    model = s.Object(foo=s.String(), bar=s.Number(), spam=nested)

    spec = Spec(Method.POST, model, Response(200, schema=s.Array(model)))

    def handle(self, data):
        return [data]
Example #6
0
class ChangePassword(ApiView):
    '''
    Change user password
    '''
    spec = Spec(
        Method.POST,
        s.Object(
            old_password=s.String(),
            new_password=s.String(),
        ),
        Response(403, description='unauthorized access'),
        Response(400, schema=Errors),
        Response(202),
    )

    def handle(self, data):
        user = getattr(self.request, 'user', None)
        if not (user or user.is_authenticated):
            return 403

        if not user.check_password(data['old_password']):
            return 400, {'errors': ['Wrong password']}

        user.set_password(data['new_password'])
        user.save(update_fields={'password'})

        return 202
Example #7
0
class FailingOutContractView(ApiView):
    spec = Spec(Method.GET, s.Query(result=s.Boolean()),
                Response(200, schema=s.Object(foo=s.String())))

    def handle(self, data):
        if data['result']:
            return {'foo': '1'}
Example #8
0
class ReturnStatusView(ApiView):
    spec = Spec(Method.GET, s.Query(result=s.String()), Response(204),
                Response(200, schema=s.Object(result=s.String())))

    def handle(self, data):
        if data['result'] == 'int':
            return 204
        elif data['result'] == 'fail':
            return 201
        return data
Example #9
0
class EmailConfirm(ApiView):
    '''
    Confirm user email
    '''
    spec = Spec(
        Method.GET,
        s.Query(
            id=s.Integer(),
            code=s.String(),
            next=s.Optional(s.String()),
        ),
        Response(301, description='redirect to the next page'),
    )

    def handle(self, data):
        code = data['code']
        user = User.objects.filter(pk=data['id']) \
            .exclude(email=None, new_email=None) \
            .filter(Q(email_confirm_code=code) | Q(new_email_confirm_code=code)) \
            .first()

        if user:
            if user.email_confirm_code == code:
                user.email_confirmed = True
                user.email_confirm_code = None
                user.is_active = True
                user.save(update_fields=[
                    'email_confirmed', 'email_confirm_code', 'is_active'
                ])

                signals.email_confirmed.send(User, user=user)

                login(self.request, user)
                signals.signup_completed.send(User, user=user)

            elif user.new_email_confirm_code == code:
                user.backend = 'django.contrib.auth.backends.ModelBackend'
                login(self.request, user)
                signals.signup_completed.send(User, user=user)

                if not User.objects.filter(email=user.new_email).exists():
                    user.email = user.new_email
                    user.new_email = None
                    user.new_email_confirm_code = None
                    user.email_confirmed = True
                    user.save(update_fields=[
                        'email', 'new_email', 'new_email_confirm_code',
                        'email_confirmed'
                    ])

        next = data['next'] or '/'

        return redirect(next)
Example #10
0
class Logout(ApiView):
    '''
    User Logout
    '''
    spec = Spec(
        Method.POST,
        s.Empty,
        Response(204),
    )

    def handle(self, data):
        logout(self.request)
        return 204
Example #11
0
def api(title, version, dev_username, dev_password):
    instance = API(middleware=[
        Falcon_Auth_Middleware(
            Basic_Auth_Backend_Middleware(dev_username, dev_password),
            exempt_routes=['/api/doc', '/api/doc/swagger.json']),
        Negotiation_Middleware()  # ,
        # Elastic_Apm_Middleware(
        #     service_name='lcp-apm',
        #     server_url=Arg_Reader.db.apm_server
        # )
    ])

    media_handlers = {
        falcon.MEDIA_JSON:
        JSON_Handler(loads=loads,
                     dumps=partial(dumps, ensure_ascii=False, sort_keys=True)),
        falcon.MEDIA_MSGPACK:
        Message_Pack_Handler(),
        falcon.MEDIA_XML:
        XML_Handler(),
        falcon.MEDIA_YAML:
        YAML_Handler()
    }
    instance.req_options.media_handlers.update(media_handlers)
    instance.resp_options.media_handlers.update(media_handlers)

    instance.add_error_handler(*Bad_Request_Handler.get())
    instance.add_error_handler(*Unsupported_Media_Type_Handler.get())

    api_spec = Spec(api=instance, title=title, version=version)
    routes(api=instance, spec=api_spec.get())
    falcon_api_doc(instance,
                   config_path='./swagger/schema.json',
                   url_prefix='/api/doc',
                   title='API doc')
    api_spec.write()

    return instance
Example #12
0
class Signup(ApiView):
    '''
    User signup (Register)
    '''
    spec = Spec(
        Method.POST,
        s.Object(
            email=s.String(),
            first_name=s.String(),
            last_name=s.String(),
            password=s.String(),
            next=s.Optional(s.String()),
        ),
        Response(202, description='user created, need to email confirmation'),
        Response(301, description='user created, redirect to the next page'),
        Response(400, schema=Errors),
    )

    def create_user(self, **kwargs):
        confirm_code = kwargs.pop('email_confirm_code', random_key())
        return User.objects.create_user(
            email_confirm_code=confirm_code,
            **kwargs,
        )

    def handle(self, data):
        data = copy.copy(data)
        next = data.pop('next', None)
        data['email'] = data['email'].lower()

        if User.objects.filter(
                Q(email=data['email']) | Q(new_email=data['email'])).exists():
            return 400, {
                'errors': ['This email is already in use, please sign in']
            }

        if settings.EMAIL_CONFIRMATION:
            user = self.create_user(**data)
            signals.user_email_confirm.send(User,
                                            user=user,
                                            email=user.email,
                                            next=next)
            return 202
        else:
            user = self.create_user(email_confirmed=True, **data)
            login(self.request, user)
            signals.signup_completed.send(User, user=user)
            return redirect(next or '/')
Example #13
0
class ResetPassword(ApiView):
    '''
    Reset password confirmation
    '''
    spec = Spec(
        Method.POST,
        s.Object(email=s.String(), ),
        Response(202),
    )

    def handle(self, data):
        email = data['email'].lower()
        user = User.objects.filter(email=email, is_active=True).first()

        if user:
            user.password_reset_code = random_key()
            user.save(update_fields={'password_reset_code'})
            signals.password_reset.send(User, user=user)

        return 202
Example #14
0
class SetPassword(ApiView):
    '''
    Set new user password
    '''
    spec = Spec(
        Method.POST,
        s.Object(
            id=s.Integer(),
            code=s.String(),
            password=s.String(),
        ),
        Response(200, schema=UserDef),
        Response(400, schema=Errors),
    )

    def handle(self, data):
        user = User.objects.filter(pk=data['id'],
                                   is_active=True,
                                   password_reset_code=data['code']).first()
        if not user:
            return 400, {'errors': ['Invalid password reset code']}

        user.set_password(data['password'])
        user.email_confirmed = True
        user.password_reset_code = None
        user.save(
            update_fields={'password', 'email_confirm', 'password_reset_code'})

        login(self.request, user)

        return 200, {
            'id': user.pk,
            'email': user.email,
            'first_name': user.first_name,
            'short_name': user.get_short_name(),
        }
Example #15
0
class ChangeEmail(ApiView):
    '''
    Change user email
    '''
    spec = Spec(Method.POST, s.Object(email=s.String(), ),
                Response(403, description='unauthorized access'),
                Response(400, schema=Errors),
                Response(200, schema=s.Object(email=s.String(), )))

    def handle(self, data):
        user = getattr(self.request, 'user', None)
        if not (user or user.is_authenticated):
            return 403

        email = data['email'].lower()

        if User.objects.exclude(
                pk=user.pk).filter(Q(email=email) | Q(new_email=email)):
            return 400, {'errors': ['This email is already in use']}

        if user.email != email:
            user.email = email
            user.save(update_fields={'email'})

        if user.email == email:
            user.new_email = None
            user.new_email_confirm_code = None
        else:
            user.new_email = email
            user.new_email_confirm_code = random_key()

            signals.user_new_email_confirm.send(User, user=user, email=email)

        user.save(update_fields={'new_email', 'new_email_confirm_code'})

        return 200, {'email': user.email}
Example #16
0
 class Test3(ApiView):
     spec = Spec(Method.GET, s.Empty)
Example #17
0
class OutContractView(ApiView):
    spec = Spec(Method.GET, s.Query(foo=s.String()),
                Response(200, schema=s.Object(foo=s.String())))

    def handle(self, data):
        return data
Example #18
0
class EchoView(ApiView):
    spec = Spec(Method.POST, s.Object(), Response(200, schema=s.Object()))

    def handle(self, data):
        return data
Example #19
0
class UnknownResponseView(ApiView):
    spec = Spec(Method.GET, s.Query(status=s.Number()), Response(204))

    def handle(self, data):
        return data['status'], data
Example #20
0
class ForbiddenView(ApiView):
    spec = Spec(Method.GET, s.Empty, Response(403))

    def handle(self, data):
        return 403
Example #21
0
class InContractView(ApiView):
    spec = Spec(Method.GET, s.Query(foo=s.Number()), Response(204))

    def handle(self, data):
        return 204
Example #22
0
 class Test4(ApiView):
     spec = Spec(Method.GET, s.Empty)
     handle = 123
Example #23
0
        class Base(ApiView):
            spec = Spec(Method.GET, s.Empty(), Response(204))

            def handle(self, data):
                pass  # pragma: no cover
Example #24
0
class PostMethod(ApiView):
    spec = Spec(Method.POST, s.Empty, Response(204))

    def handle(self, data):
        return 204