From c9b3d3a833e73d0c56e8594c2addbf23cbbc1055 Mon Sep 17 00:00:00 2001 From: knst-kotov Date: Tue, 29 Jun 2021 13:26:46 +0300 Subject: [PATCH] register user, sign in and sign out working --- auth/authenticate.py | 3 +-- auth/authorize.py | 4 ++-- auth/identity.py | 2 +- auth/token.py | 2 +- auth/validations.py | 3 ++- main.py | 4 ++-- orm/__init__.py | 3 +++ orm/user.py | 8 +++---- resolvers/__init__.py | 4 ++-- resolvers/auth.py | 26 ++++++++++---------- schema.graphql | 2 +- schema/schema.auth.graphql | 46 ++++++++++++++++++++++++++++++++++++ schema/schema.common.graphql | 2 ++ settings.py | 2 +- 14 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 schema/schema.auth.graphql create mode 100644 schema/schema.common.graphql diff --git a/auth/authenticate.py b/auth/authenticate.py index 7e560ce6..1eea1118 100644 --- a/auth/authenticate.py +++ b/auth/authenticate.py @@ -56,9 +56,8 @@ class JWTAuthenticate(AuthenticationBackend): if JWT_AUTH_HEADER not in request.headers: return AuthCredentials(scopes=[]), AuthUser(user_id=None) - auth = request.headers[JWT_AUTH_HEADER] + token = request.headers[JWT_AUTH_HEADER] try: - scheme, token = auth.split() payload = await _Authenticate.verify(token) except Exception as exc: return AuthCredentials(scopes=[], error_message=str(exc)), AuthUser(user_id=None) diff --git a/auth/authorize.py b/auth/authorize.py index 31535ba8..5ca2212b 100644 --- a/auth/authorize.py +++ b/auth/authorize.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from auth.token import Token from redis import redis from settings import JWT_LIFE_SPAN -from validations import User +from auth.validations import User class Authorize: @@ -30,7 +30,7 @@ class Authorize: except: # noqa pass else: - await redis.execute("DEL", f"{payload.id}-{token}") + await redis.execute("DEL", f"{payload.user_id}-{token}") return True @staticmethod diff --git a/auth/identity.py b/auth/identity.py index cb219a79..8af26a2c 100644 --- a/auth/identity.py +++ b/auth/identity.py @@ -2,7 +2,7 @@ from auth.password import Password from exceptions import InvalidPassword, ObjectNotExist from orm import User as OrmUser from orm.base import global_session -from validations import User +from auth.validations import User class Identity: diff --git a/auth/token.py b/auth/token.py index b02abcd6..d3fa5715 100644 --- a/auth/token.py +++ b/auth/token.py @@ -3,7 +3,7 @@ from datetime import datetime import jwt from settings import JWT_ALGORITHM, JWT_SECRET_KEY -from validations import PayLoad, User +from auth.validations import PayLoad, User class Token: diff --git a/auth/validations.py b/auth/validations.py index 0c427641..e63a5e14 100644 --- a/auth/validations.py +++ b/auth/validations.py @@ -20,9 +20,10 @@ class PayLoad(BaseModel): class CreateUser(BaseModel): + email: Text username: Text # age: Optional[int] # phone: Optional[Text] password: Optional[Text] -# TODO: update validations \ No newline at end of file +# TODO: update validations diff --git a/main.py b/main.py index 062b5747..2b94f25e 100644 --- a/main.py +++ b/main.py @@ -6,12 +6,12 @@ from starlette.applications import Starlette from starlette.middleware import Middleware from starlette.middleware.authentication import AuthenticationMiddleware -from authority.authenticate import JWTAuthenticate +from auth.authenticate import JWTAuthenticate from redis import redis from resolvers.base import resolvers import_module('resolvers') -schema = make_executable_schema(load_schema_from_path("schema.graphql"), resolvers) +schema = make_executable_schema(load_schema_from_path("schema/"), resolvers) middleware = [Middleware(AuthenticationMiddleware, backend=JWTAuthenticate())] diff --git a/orm/__init__.py b/orm/__init__.py index 4b92c681..7f0bb6ba 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -1,4 +1,7 @@ from orm.rbac import Operation, Permission, Role from orm.user import User +from orm.base import Base, engine __all__ = ["User", "Role", "Operation", "Permission"] + +Base.metadata.create_all(engine) diff --git a/orm/user.py b/orm/user.py index 2cdab429..be6db8d2 100644 --- a/orm/user.py +++ b/orm/user.py @@ -9,11 +9,11 @@ from orm.base import Base class User(Base): __tablename__ = 'user' - name: str = Column(String, nullable=False, comment="Name") + email: str = Column(String, nullable=False) + username: str = Column(String, nullable=False, comment="Name") password: str = Column(String, nullable=False, comment="Password") - # phone: str = Column(String, comment="Phone") - # age: int = Column(Integer, comment="Age") - role_id: int = Column(ForeignKey("role.id"), nullable=False, comment="Role") + + role_id: int = Column(ForeignKey("role.id"), nullable=True, comment="Role") @classmethod def get_permission(cls, user_id): diff --git a/resolvers/__init__.py b/resolvers/__init__.py index 160ab3b0..0e858f2c 100644 --- a/resolvers/__init__.py +++ b/resolvers/__init__.py @@ -1,3 +1,3 @@ -from resolvers.login import get_user, login, logout, register +from resolvers.auth import sign_in, sign_out, register -__all__ = ["get_user", "login", "logout", "register"] +__all__ = ["sign_in", "sign_out", "register"] diff --git a/resolvers/auth.py b/resolvers/auth.py index fa218a74..1b1b38b8 100644 --- a/resolvers/auth.py +++ b/resolvers/auth.py @@ -11,35 +11,35 @@ from resolvers.base import mutation, query from settings import JWT_AUTH_HEADER -@mutation.field("SignUp") -async def register(*_, create: dict = None) -> User: - create_user = CreateUser(**create) +@mutation.field("registerUser") +async def register(*_, input: dict = None) -> User: + create_user = CreateUser(**input) create_user.password = Password.encode(create_user.password) return User.create(**create_user.dict()) -@query.field("SignIn") -async def login(_, info: GraphQLResolveInfo, id: int, password: str) -> str: +@query.field("signIn") +async def sign_in(_, info: GraphQLResolveInfo, id: int, password: str): try: device = info.context["request"].headers['device'] except KeyError: device = "pc" auto_delete = False if device == "mobile" else True user = Identity.identity(user_id=id, password=password) - return await Authorize.authorize(user, device=device, auto_delete=auto_delete) + token = await Authorize.authorize(user, device=device, auto_delete=auto_delete) + return {"status" : True, "token" : token} -# TODO: implement some queries, ex. @query.field("isUsernameFree") - -@query.field("logout") +@query.field("signOut") @login_required -async def logout(_, info: GraphQLResolveInfo, id: int) -> bool: +async def sign_out(_, info: GraphQLResolveInfo): token = info.context["request"].headers[JWT_AUTH_HEADER] - return await Authorize.revoke(token) + status = await Authorize.revoke(token) + return {"status" : status} -@query.field("getUser") -@login_required +#@query.field("getUser") +#@login_required async def get_user(*_, id: int): return global_session.query(User).filter(User.id == id).first() diff --git a/schema.graphql b/schema.graphql index f882b49e..66ea9e01 100644 --- a/schema.graphql +++ b/schema.graphql @@ -60,7 +60,7 @@ type Mutation { # proposal createProposal(shout: Int!, range: String!): Boolean! updateProposal(proposal: Int!, body: String!): Boolean! - removeProposal(proposal: Int!) + removeProposal(proposal: Int!): Boolean! approveProposal(proposal: Int!): Boolean! } diff --git a/schema/schema.auth.graphql b/schema/schema.auth.graphql new file mode 100644 index 00000000..0f3404ff --- /dev/null +++ b/schema/schema.auth.graphql @@ -0,0 +1,46 @@ + +type Role { + id: Int! + name: String! +} + +type User { + createdAt: DateTime! + email: String + emailConfirmed: Boolean + id: Int! + muted: Boolean + rating: Int + roles: [Role!]! + updatedAt: DateTime! + username: String + userpic: String + userpicId: String + wasOnlineAt: DateTime +} + +input registerUserInput { + email: String! + username: String! + password: String! +} + +type signInPayload { + status: Boolean! + error: String + token: String +} + +type signOutPayload { + status: Boolean! + error: String +} + +type Query{ + signIn(id: Int!, password: String!): signInPayload! + signOut: signOutPayload! +} + +type Mutation{ + registerUser(input: registerUserInput!): User! +} diff --git a/schema/schema.common.graphql b/schema/schema.common.graphql new file mode 100644 index 00000000..bada3b71 --- /dev/null +++ b/schema/schema.common.graphql @@ -0,0 +1,2 @@ + +scalar DateTime diff --git a/settings.py b/settings.py index aca824cb..be78aa0f 100644 --- a/settings.py +++ b/settings.py @@ -5,4 +5,4 @@ JWT_ALGORITHM = "HS256" JWT_SECRET_KEY = "8f1bd7696ffb482d8486dfbc6e7d16dd-secret-key" JWT_LIFE_SPAN = 24 * 60 * 60 # seconds JWT_AUTH_HEADER = "Auth" -REDIS_URL = "redis://redis" +REDIS_URL = "redis://127.0.0.1"