Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sanic-openapi and sanic-jwt #74

Closed
saeedghx68 opened this issue Nov 23, 2018 · 4 comments
Closed

sanic-openapi and sanic-jwt #74

saeedghx68 opened this issue Nov 23, 2018 · 4 comments

Comments

@saeedghx68
Copy link

saeedghx68 commented Nov 23, 2018

I use sanic-openapi and sanic-jwt
How to set @doc.consumes and @doc.produces for below API's of sanic-jwt

POST/auth/
GET/auth/me/
GET/auth/verify/

@saeedghx68 saeedghx68 reopened this Nov 25, 2018
@saeedghx68 saeedghx68 changed the title Authorized Option in swagger sanic-openapi and sanic-jwt Nov 25, 2018
@saeedghx68
Copy link
Author

I implement by this code

from sanic_jwt.endpoints  import AuthenticateEndpoint
from sanic_openapi import doc

class LoginSwDoc:
    username = doc.String("Username", required=True)
    password = doc.String("Password", required=True)

# add swagger doc to sanic JWT method
AuthenticateEndpoint.decorators.extend([
    doc.summary("Authenticate user and get token"),
    doc.consumes(LoginSwDoc, location='body'),
    doc.produces(LoginSwDoc),
    doc.consumes({'AUTHORIZATION': str}, location='header'),
])

@nomed
Copy link
Contributor

nomed commented Oct 12, 2020

Hi,

tried on sanic 20.9.0 with no success.

Is it supposed to work also on more recent releases ?

@digitalkaoz
Copy link

digitalkaoz commented Nov 3, 2020

this was my attempt:

def document_auth_bp():
    from sanic_jwt.endpoints import RetrieveUserEndpoint, AuthenticateEndpoint, VerifyEndpoint, RefreshEndpoint

    inner_me = RetrieveUserEndpoint.get

    @doc.summary("returns the user for this JWT Token")
    @doc.consumes({'AUTHORIZATION': str}, location='header')
    @doc.produces(User)
    async def doc_me(self, request, *args, **kwargs):
        return await inner_me(self, request, *args, **kwargs)

    RetrieveUserEndpoint.get = doc_me

    inner_auth = AuthenticateEndpoint.post

    @doc.summary("login a user")
    @doc.consumes(doc.JsonBody({
        "username": doc.String("the username"),
        "password": doc.String("the password"),
    }), location="body")
    @doc.response(401, None, description="invalid credentials")
    @doc.response(200, {"access_token": str, "refresh_token": str}, description="the token to use for api interaction")
    async def doc_auth(self, request, *args, **kwargs):
        return await inner_auth(self, request, *args, **kwargs)

    AuthenticateEndpoint.post = doc_auth

    inner_verify = VerifyEndpoint.get

    @doc.summary("verifies a JWT")
    @doc.consumes({'AUTHORIZATION': str}, location='header')
    @doc.response(401, None, description="Token is invalid or expired")
    @doc.response(200, {"valid": True}, description="Token is valid")
    async def doc_verify(self, request, *args, **kwargs):
        return await inner_verify(self, request, *args, **kwargs)

    VerifyEndpoint.get = doc_verify

    inner_refresh = RefreshEndpoint.post

    @doc.summary("generates a new access token with the refresh token")
    @doc.consumes({'AUTHORIZATION': str}, location='header')
    @doc.consumes(doc.JsonBody({
        "refresh_token": doc.String("the refresh token"),
    }), location="body")
    @doc.response(401, None, description="Token is invalid or expired")
    @doc.response(200, {"access_token": str}, description="the new access token")
    async def doc_refresh(self, request, *args, **kwargs):
        return await inner_refresh(self, request, *args, **kwargs)

    RefreshEndpoint.post = doc_refresh

document_auth_bp()

jwt = Initialize(
    app,
    ...
)

i feel pretty dirty right now, but it works, would love to see a cleaner solution!

@nomed

@quadhead
Copy link

quadhead commented Nov 4, 2020

My solution:

sanicjwt = Initialize(
    app,
    ...
)

for route in sanicjwt.bp.routes:
    view = route.handler.view_class
    for http_method in route.methods:
        h = getattr(view, http_method.lower(), None)
        if h:
            name = route.handler.__name__
            d = doc.route_specs[h]
            if name == "AuthenticateEndpoint":
                d.summary = "Authenticate user and get token"
            if name == "RetrieveUserEndpoint":
                d.summary = "Retrieve current user"
            if name == "VerifyEndpoint":
                d.summary = "Verify token"
            if name == "RefreshEndpoint":
                d.summary = "Generate new token using refresh token"

Seems a little bit more elegant...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants