-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
development of users collection api endpoints
- Loading branch information
1 parent
896a7f8
commit 1c2fdd9
Showing
10 changed files
with
146 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,12 @@ | ||
from flask import Flask | ||
from flask_restful import Api | ||
from webserver.resources.users_collection import UsersCollection | ||
from flask_bcrypt import Bcrypt | ||
|
||
app = Flask(__name__) | ||
api = Api(app) | ||
bcrypt = Bcrypt(app) | ||
|
||
from webserver.resources.users_collection import UsersCollection | ||
from webserver.resources.users import Users | ||
api.add_resource(UsersCollection, "/users") | ||
api.add_resource(Users, "/users/<string:user_id>") |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class DataFormatError(Exception): | ||
""" Raised when unrecognized data format is given """ | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class InvalidUserException(Exception): | ||
""" Raised when invalid userid is entered """ | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
from webserver.database_manager import users_collection | ||
from webserver.classes.exceptions.data_format import DataFormatError | ||
from webserver.classes.exceptions.invalid_userid import InvalidUserException | ||
from jsonschema import validate | ||
from flask_bcrypt import Bcrypt | ||
import pymongo | ||
|
||
class User(object): | ||
""" | ||
This class interacts with the database to perform database operations related to the | ||
Users collection. | ||
""" | ||
def __init__(self): | ||
self.schema = { | ||
"type": "object", | ||
"properties": { | ||
"userId": {"type": "string"}, | ||
"name": {"type": "string"}, | ||
"email": {"type": "string"}, | ||
"password": {"type": "string"} | ||
}, | ||
"required": ["name", "userId", "password"], | ||
"additionalProperties": False | ||
} | ||
|
||
def user_exists(self, userId: str) -> bool: | ||
result = users_collection.find({"_id": userId}) | ||
return result != None | ||
|
||
def add_user(self, data: dict, bcrypt: Bcrypt): | ||
""" | ||
Adds a new user to the Users collection. | ||
Returns the inserted id if operation was successful. Returns None otherwise. | ||
""" | ||
# raises exception is invalid data | ||
self.validate_data(data) | ||
data["_id"] = data["userId"] | ||
del data["userId"] | ||
|
||
unhashed_password = data["password"] | ||
data["password"] = bcrypt.generate_password_hash(unhashed_password).decode("utf-8") | ||
|
||
try: | ||
ret = users_collection.insert_one(data) | ||
return ret.inserted_id | ||
except pymongo.errors.DuplicateKeyError: | ||
pass | ||
return None | ||
|
||
def login_user(self, userId: str, password: str, bcrypt: Bcrypt): | ||
""" | ||
Queries the database with the given userId and verifies the given password. | ||
Raises: | ||
InvalidUserException: if userId does not exist | ||
Returns: | ||
True, if password is valid. False otherwise. | ||
""" | ||
doc = users_collection.find_one({"_id": userId}) | ||
if (doc == None): | ||
raise InvalidUserException(f'{userId} does not exist') | ||
valid_password = bcrypt.check_password_hash(doc["password"], password) | ||
return valid_password | ||
|
||
def validate_data(self, data: dict) -> None: | ||
# validate the data | ||
if (isinstance(data, dict)): | ||
validate(instance=data, schema=self.schema) | ||
else: | ||
raise DataFormatError("Invalid data format") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
Flask==1.1.2 | ||
Flask-RESTful==0.3.8 | ||
flask-bcrypt | ||
pymongo | ||
jsonschema |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from email.policy import default | ||
from flask_restful import Resource | ||
from flask import request | ||
from webserver.app import bcrypt | ||
from webserver.classes.user import User | ||
from webserver.classes.exceptions.invalid_userid import InvalidUserException | ||
|
||
user = User() | ||
|
||
class Users(Resource): | ||
def get(self, user_id): | ||
""" | ||
Handles a GET request. | ||
Expects a "password" key in the request body. | ||
Returns: | ||
status code 404: if the given user_id does not exist | ||
status code 401: if invalid password was given | ||
status code 200: if login was successful | ||
""" | ||
try: | ||
password = request.args.get("password", default=None, type=str) | ||
if password is None: | ||
return {"response": "password field was not given"}, 400 | ||
|
||
if (user.login_user(user_id, password, bcrypt)): | ||
return {"response": "login successful"}, 200 | ||
else: | ||
return {"response": "invalid password"}, 401 | ||
except InvalidUserException: | ||
return {"response": "invalid user_id"}, 404 | ||
except Exception as e: | ||
return {"response": str(e)}, 500 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,29 @@ | ||
from flask_restful import Resource | ||
from flask import request | ||
from webserver.database_manager import users_collection | ||
from webserver.app import bcrypt | ||
from webserver.classes.user import User | ||
import jsonschema | ||
from webserver.classes.exceptions.data_format import DataFormatError | ||
|
||
user = User() | ||
|
||
class UsersCollection(Resource): | ||
def post(self): | ||
return {"response": "hello world"}, 200 | ||
""" | ||
Handles a POST request. Inserts a new user into the Users collection. | ||
Returns: | ||
status code 201 if the user was successfully created. | ||
status code 409 if the given userId already exists. | ||
""" | ||
try: | ||
data = request.get_json() | ||
ret = user.add_user(data, bcrypt) | ||
status = 201 | ||
if (ret == None): | ||
status = 409 | ||
return {"userId": ret}, status | ||
except (jsonschema.exceptions.ValidationError, DataFormatError) as e: | ||
return {"response": str(e)}, 400 | ||
except Exception as e: | ||
return {"response": str(e)}, 500 |