diff --git a/Auth/AuthAPI.py b/Auth/AuthAPI.py index b903496..c140476 100644 --- a/Auth/AuthAPI.py +++ b/Auth/AuthAPI.py @@ -1,7 +1,48 @@ # Score API here -from flask import Blueprint +from flask import Blueprint, request, jsonify, current_app import sys -from db import db +from db import db, cred +import jwt sys.path.append("../") auth_api = Blueprint("auth", __name__) +@auth_api.route('/register', methods = ["POST"]) +def reg(): + + def regdet(argsform): + username = argsform.get('username') + hashedPassword = argsform.get('passwordHash') + + if (username == '') or (hashedPassword == ''): + return jsonify({"Status" : "Failed", "Message" : "Username or Password not available"}) + else: + cred.append({"username" : username, "passwordHash" : hashedPassword}) + return jsonify({"Status" : "Success", "Message" : "Registered"}) + + if request.args.get('username'): + return regdet(request.args) + + elif request.form.get('username'): + return regdet(request.form) + +@auth_api.route('/login', methods = ["POST"]) +def login(): + + def logindetails(): + username = request.form.get('username') + hashedPassword = request.form.get('passwordHash') + return username, hashedPassword + + det = logindetails() + username = det[0] + hashedPassword = det[1] + + checkuser = {"username":username, "passwordHash":hashedPassword} + if checkuser in cred: + token = jwt.encode({'userID': username, + 'passwordHash': hashedPassword + }, current_app.config['SECRET_KEY'], algorithm="HS256") + + return jsonify({'Status': 'Success', 'token': token}) + + return jsonify({'Status': 'Failed', 'Message': 'Username or Password does not match'}) \ No newline at end of file diff --git a/Auth/__pycache__/AuthAPI.cpython-37.pyc b/Auth/__pycache__/AuthAPI.cpython-37.pyc new file mode 100644 index 0000000..547622a Binary files /dev/null and b/Auth/__pycache__/AuthAPI.cpython-37.pyc differ diff --git a/Profiles/ProfilesAPI.py b/Profiles/ProfilesAPI.py index 4467047..9c352b2 100644 --- a/Profiles/ProfilesAPI.py +++ b/Profiles/ProfilesAPI.py @@ -1,7 +1,56 @@ # Profile API here -from flask import Blueprint +from flask import Blueprint, request, jsonify import sys from db import db sys.path.append("../") profiles_api = Blueprint("profiles", __name__) + +@profiles_api.route('//', methods = ["GET"]) +def retrieve(id): + if id > len(db)-1: + return jsonify({"Status" : "Error", "Message" : "Don't have"}) + + else: + dets = db[id] + return jsonify({"Status" : "Success", "Details" : dets}) + +@profiles_api.route('/', methods = ["POST"])#wont work on googlechrome only on postman,check on postman +def postid(): + newprofile = {} + newprofname = request.form.get('name') + newprofile["name"] = newprofname + + db.append(newprofile) + + return jsonify({"Status" : "Success", "Details" : newprofile}) + + +@profiles_api.route('//', methods = ["DELETE"]) +def deleteid(id): + if id > len(db)-1: + return jsonify({"Status" : "Error", "Message" : "Don't have"}) + + else: + deleted = db[id] + del db[id] + + return jsonify({"Status" : "Success", "New db" : db, "Deleted profile" : deleted}) + + +@profiles_api.route('//score', methods = ["GET"]) +def getabovemin(id): + if id > len(db)-1: + return jsonify({"Status" : "Error", "Message" : "No such ID"}) + + min = request.args.get('minScore') + s = db[id]["scores"] + + if min == '': + return jsonify({"Status" : "Success", "Details" : s}) + + score = list(filter(lambda s: s > int(min), s))#use assig + + + return jsonify({"Status" : "Success", "Details" : score}) + diff --git a/Profiles/__pycache__/ProfilesAPI.cpython-37.pyc b/Profiles/__pycache__/ProfilesAPI.cpython-37.pyc new file mode 100644 index 0000000..95452b1 Binary files /dev/null and b/Profiles/__pycache__/ProfilesAPI.cpython-37.pyc differ diff --git a/README.md b/README.md index 08c35ed..7a0d056 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,114 @@ # RHDEV-BE-2-flask -Homewwork template for BE training lesson 2: Flask and web servers - -Setup a basic API to simulate a website that tracks profiles and scores for exams - -A simulated db is provided. Note that the db will not be updated between runs - In main: -GET / homepage that returns a welcome message - In profiles API (/profiles prefix) -GET /{id} to retrieve the name and all scores of a profile -POST /profiles to create a new profile (name only) -DELETE /{id} to delete a profile -GET /{id}/score?minScore= to retrieve all scores of a profile, above the min score - In authentication API (/auth prefix) -POST /register stores a username and hashedPassword (given as hashed) -Store it in a local array -Login /login checks if the provided information is valid and return a jwt token + success message - -Give a reasonable return format with appropriate status code and messages. -{“message” : “success/fail”, “data”:””} -Also submit a simplified documentation of your API. You can use the format below. - - - -OPTIONALS: -Add environmental variables into the system (for jwt signing secret) -In the login route, check if jwt token is provided and valid -Assume URL argument has token “?token=sdlkaskdnalsdnsald” -See if username and password field arre present +1) GET / + +Get welcome message + +Function used : hello() +Source: main.py + +Parameters : None + +Response : welcome message string + +Example : + halo + +2) GET /profiles// + +retrieve the names and scores + +Function used : retrieve(id) +Source: ProfilesAPI.py + +Parameters : None + +Response : JSON of status and profile + +Example : + {"Status" : "Success", "Details" : {"name": "Nobel", "scores": [1, 2, 3, 4, 5]} } + +3) POST /profiles + +Create new profile + +Function used : postid() +Source: ProfilesAPI.py + +Parameters : None + +Response : JSON of status and details of new profile + +Example : + {"Status" : "Success", "Details" : {"name": "Vina"}} + +4) DELETE /profiles// + +Delete profile + +Function used : deleteid(id) +Source: ProfilesAPI.py + +Parameters : None + +Response : JSON of status and details of deleted profile. If failed then json of status and message 'No such ID' + +Example : + {"Status" : "Success", "Details" : {"name": "Nobel", "scores": [1, 2, 3, 4, 5]}} + or +{"Status" : "Error", "Message" : "No such ID"} + +5) GET /profiles//score + +Get all scores of a profile, above the min score and if min score not provided, return all scores + +Function used : getabovemin(id) +Source: ProfilesAPI.py + +Parameters : min + +Response : JSON of status and details of scores. If failed then json of status and message 'Don't have' + +Example : if min=3``` {"Status" : "Success", "Details" : [4, 5]}} + or +{"Status" : "Error", "Message" : "Don't have"} + or if min= +{"Status" : "Success", "Details" : [1, 2 ,3, 4, 5]}} + +6) POST /auth/register + +Stores a username and hashedPassword (given as hashed) and store it in a local array ('creds') + +Function used : reg() +Source: AuthAPI.py + +Parameters : + +username (Required) +Username of user + +passwordHash (Required) +Password of user + +Response : JSON of message - registered and status. If failed then json of status and message 'No such ID' + +Example : +{"Message": "Registered","Status": "Success"} + + +6) POST /auth/login + +Checks if the provided information is valid and return a jwt token + success message + +Function used : login() +Source: AuthAPI.py + +Parameters : + +username (Required) +Username of user + +passwordHash (Required) +Password of user + +Response : JWT token and status. + diff --git a/__pycache__/db.cpython-37.pyc b/__pycache__/db.cpython-37.pyc new file mode 100644 index 0000000..45eea8b Binary files /dev/null and b/__pycache__/db.cpython-37.pyc differ diff --git a/db.py b/db.py index 777200b..50f9713 100644 --- a/db.py +++ b/db.py @@ -9,3 +9,6 @@ "name": "Hui Hui", "scores": [9, 29, 34] }] +cred = [{"username" : "Dev", "passwordHash" : "12345"}] + +AUTH_SECRET_KEY = 'key1' \ No newline at end of file diff --git a/main.py b/main.py index fc7fbd4..bfed903 100644 --- a/main.py +++ b/main.py @@ -7,6 +7,12 @@ # Write your flask code here app = Flask(__name__) - +app.config['SECRET_KEY'] = 'Key1' app.register_blueprint(profiles_api, url_prefix="/profiles") app.register_blueprint(auth_api, url_prefix="/auth") + +@app.route("/", methods = ["GET"]) +def hello(): + return "halo" +if __name__== "main": + app.run("localhost", port=8080) \ No newline at end of file