diff --git a/auth_utils.py b/auth_utils.py new file mode 100644 index 00000000..b8af071c --- /dev/null +++ b/auth_utils.py @@ -0,0 +1,46 @@ +import jwt +from hashlib import md5 + +# see: settings.py +JWT_SECRET_KEY = "my secret key" +JWT_ALGORITHM = "HS256" + +JWT_AUTH_HEADER = "HTTP_AUTHORIZATION" + + +# see: auth.password.Password +def password_to_hash(password): + return md5(password.encode('utf-8')).hexdigest() + +def verify_password(password, hash): + return password_to_hash(password) == hash + +# see: auth.auth.token.Token +def jwt_encode(user): + payload = { + "user_id" : user.id + } + + token = jwt.encode(payload, JWT_SECRET_KEY, JWT_ALGORITHM) + + if isinstance(token, bytes): + return token.decode('utf-8') + + return token + +def jwt_decode(token): + try: + payload = jwt.decode(token, JWT_SECRET_KEY, algorithms = [JWT_ALGORITHM]) + except jwt.DecodeError: + raise Exception("Error decoding signature") + except jwt.InvalidTokenError: + raise Exception("Invalid token") + + user_id = payload["user_id"] + return user_id + +# see: auth.authorize +def authorize(request): + token = request.headers.get(JWT_AUTH_HEADER, '') + user_id = jwt_decode(token) + return user_id diff --git a/message_service.py b/message_service.py index 447d274d..5a1698f3 100644 --- a/message_service.py +++ b/message_service.py @@ -11,6 +11,9 @@ from peewee import * import asyncio +import auth_utils + + type_defs = load_schema_from_path("schema.graphql") db = SqliteDatabase('discours.db') @@ -19,6 +22,16 @@ class User(Model): username = CharField() email = CharField() createdAt = DateTimeField(default=datetime.now) + muted = BooleanField(default=False) + rating = IntegerField(default=0) + # roles = + updatedAt = DateTimeField(default=datetime.now) + username = CharField() + userpic = CharField(default="") + userpicId = CharField(default="") + wasOnlineAt = DateTimeField(default=datetime.now) + + password = CharField() class Meta: database = db @@ -38,7 +51,11 @@ class Message(Model): db.connect() db.create_tables([User, Message]) -#only_user = User.create(username = "admin", email = "knst.kotov@gmail.com") +#only_user = User.create( +# username = "admin", +# email = "knst.kotov@gmail.com", +# password = auth_utils.password_to_hash("12345") +#) only_user = User.get(User.username == "admin") @@ -65,17 +82,43 @@ def resolve_get_messages(_, info, count, page): mutation = MutationType() +@mutation.field("signIn") +def resolve_sign_in(_, info, email, password): + try: + user = User.get(User.email == email) + except DoesNotExist as err: + return { + "status" : False, + "error" : "invalid username or password" + } + + if auth_utils.verify_password(password, user.password) : + return { + "status" : True, + "token" : auth_utils.jwt_encode(user) + } + + return { + "status" : False, + "error" : "invalid username or password" + } + @mutation.field("createMessage") def resolve_create_message(_, info, input): + request = info.context["request"] + try: + user_id = auth_utils.authorize(request) + user = User.get(User.id == user_id) + new_message = Message.create( - author = only_user, + author = user, body = input["body"], replyTo = input.get("replyTo") ) except Exception as err: return { - "status" : false, + "status" : False, "message" : err } @@ -90,6 +133,17 @@ def resolve_create_message(_, info, input): @mutation.field("updateMessage") def resolve_update_message(_, info, input): + request = info.context["request"] + + try: + user_id = auth_utils.authorize(request) + user = User.get(User.id == user_id) + except Exception as err: + return { + "status" : False, + "message" : err + } + message_id = input["id"] body = input["body"] @@ -101,6 +155,12 @@ def resolve_update_message(_, info, input): updated_message = all_messages[message_id] + if updated_message.author != user: + return { + "status" : False, + "error" : "update this message denied" + } + updated_message.body = body #updated_message.updatedAt = datetime.now try: diff --git a/schema.graphql b/schema.graphql index 79a55f1f..f882b49e 100644 --- a/schema.graphql +++ b/schema.graphql @@ -160,4 +160,4 @@ type Like { shout: Int user: Int value: Int! -} \ No newline at end of file +}