Started with the login function and it works more or less :-) #37
8 changed files with 300 additions and 58 deletions
|
@ -1,13 +1,51 @@
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
from flask import Flask
|
import flask
|
||||||
import flask_sqlalchemy
|
import flask_sqlalchemy
|
||||||
import flask_praetorian
|
import flask_praetorian
|
||||||
import flask_cors
|
import flask_cors
|
||||||
|
|
||||||
import os
|
db = flask_sqlalchemy.SQLAlchemy()
|
||||||
|
guard = flask_praetorian.Praetorian()
|
||||||
|
cors = flask_cors.CORS()
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
|
# A generic user model that might be used by an app powered by flask-praetorian
|
||||||
|
class User(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
username = db.Column(db.Text, unique=True)
|
||||||
|
password = db.Column(db.Text)
|
||||||
|
roles = db.Column(db.Text)
|
||||||
|
is_active = db.Column(db.Boolean, default=True, server_default='true')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rolenames(self):
|
||||||
|
try:
|
||||||
|
return self.roles.split(',')
|
||||||
|
except Exception:
|
||||||
|
return []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def lookup(cls, username):
|
||||||
|
return cls.query.filter_by(username=username).one_or_none()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def identify(cls, id):
|
||||||
|
return cls.query.get(id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def identity(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
return self.is_active
|
||||||
|
|
||||||
|
|
||||||
|
# Initialize flask app for the example
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
app.config['SECRET_KEY'] = 'top secret'
|
||||||
|
app.config['JWT_ACCESS_LIFESPAN'] = {'hours': 24}
|
||||||
|
app.config['JWT_REFRESH_LIFESPAN'] = {'days': 30}
|
||||||
# Read environment variables
|
# Read environment variables
|
||||||
if "DEBUG" in os.environ and os.environ["DEBUG"] == 'yes':
|
if "DEBUG" in os.environ and os.environ["DEBUG"] == 'yes':
|
||||||
debug = True
|
debug = True
|
||||||
|
@ -22,26 +60,93 @@ if "PORT" in os.environ:
|
||||||
else:
|
else:
|
||||||
port = 5000
|
port = 5000
|
||||||
|
|
||||||
|
# Initialize the flask-praetorian instance for the app
|
||||||
|
guard.init_app(app, User)
|
||||||
|
|
||||||
db = flask_sqlalchemy.SQLAlchemy()
|
# Initialize a local database for the example
|
||||||
guard = flask_praetorian.Praetorian()
|
app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{os.path.join(os.getcwd(), 'database.db')}"
|
||||||
cors = flask_cors.CORS()
|
db.init_app(app)
|
||||||
|
|
||||||
class User(db.Model):
|
# Initializes CORS so that the api_tool can talk to the example app
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
cors.init_app(app)
|
||||||
username = db.Column(db.Text, unique=True)
|
|
||||||
password = db.Column(db.Text)
|
# Add users for the example
|
||||||
|
with app.app_context():
|
||||||
|
db.create_all()
|
||||||
|
if db.session.query(User).filter_by(username='Yasoob').count() < 1:
|
||||||
|
db.session.add(User(
|
||||||
|
username='Yasoob',
|
||||||
|
password=guard.hash_password('strongpassword'),
|
||||||
|
roles='admin'
|
||||||
|
))
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
# Set up some routes for the example
|
||||||
@app.route('/')
|
@app.route('/api/')
|
||||||
def home():
|
def home():
|
||||||
return "Hello World"
|
return {"Hello": "World"}, 200
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/login', methods=['POST'])
|
||||||
|
def login():
|
||||||
|
"""
|
||||||
|
Logs a user in by parsing a POST request containing user credentials and
|
||||||
|
issuing a JWT token.
|
||||||
|
.. example::
|
||||||
|
$ curl http://localhost:5000/api/login -X POST \
|
||||||
|
-d '{"username":"Yasoob","password":"strongpassword"}'
|
||||||
|
"""
|
||||||
|
req = flask.request.get_json(force=True)
|
||||||
|
username = req.get('username', None)
|
||||||
|
password = req.get('password', None)
|
||||||
|
user = guard.authenticate(username, password)
|
||||||
|
ret = {'access_token': guard.encode_jwt_token(user)}
|
||||||
|
return ret, 200
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/refresh', methods=['POST'])
|
||||||
|
def refresh():
|
||||||
|
"""
|
||||||
|
Refreshes an existing JWT by creating a new one that is a copy of the old
|
||||||
|
except that it has a refrehsed access expiration.
|
||||||
|
.. example::
|
||||||
|
$ curl http://localhost:5000/api/refresh -X GET \
|
||||||
|
-H "Authorization: Bearer <your_token>"
|
||||||
|
"""
|
||||||
|
print("refresh request")
|
||||||
|
old_token = request.get_data()
|
||||||
|
new_token = guard.refresh_jwt_token(old_token)
|
||||||
|
ret = {'access_token': new_token}
|
||||||
|
return ret, 200
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/protected')
|
||||||
|
@flask_praetorian.auth_required
|
||||||
|
def protected():
|
||||||
|
"""
|
||||||
|
A protected endpoint. The auth_required decorator will require a header
|
||||||
|
containing a valid JWT
|
||||||
|
.. example::
|
||||||
|
$ curl http://localhost:5000/api/protected -X GET \
|
||||||
|
-H "Authorization: Bearer <your_token>"
|
||||||
|
"""
|
||||||
|
return {'message': f'protected endpoint (allowed user {flask_praetorian.current_user().username})'}
|
||||||
|
|
||||||
@app.route('/time')
|
@app.route('/time')
|
||||||
def get_current_time():
|
def get_current_time():
|
||||||
return {'time': time.time()}
|
return {'time': time.time()}
|
||||||
|
|
||||||
|
|
||||||
|
# Run the example
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=5000)
|
||||||
|
import time
|
||||||
|
from flask import Flask
|
||||||
|
import flask_sqlalchemy
|
||||||
|
import flask_praetorian
|
||||||
|
import flask_cors
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=debug, host=host, port=port)
|
app.run(debug=debug, host=host, port=port)
|
||||||
|
|
136
frontend/package-lock.json
generated
136
frontend/package-lock.json
generated
|
@ -5197,11 +5197,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domhandler": {
|
"domhandler": {
|
||||||
"version": "2.4.2",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
|
||||||
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
|
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"domelementtype": "1"
|
"domelementtype": "^2.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domutils": {
|
"domutils": {
|
||||||
|
@ -7330,22 +7337,40 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"htmlparser2": {
|
"htmlparser2": {
|
||||||
"version": "3.10.1",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||||
"integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
|
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"domelementtype": "^1.3.1",
|
"domelementtype": "^2.0.1",
|
||||||
"domhandler": "^2.3.0",
|
"domhandler": "^4.0.0",
|
||||||
"domutils": "^1.5.1",
|
"domutils": "^2.5.2",
|
||||||
"entities": "^1.1.1",
|
"entities": "^2.0.0"
|
||||||
"inherits": "^2.0.1",
|
|
||||||
"readable-stream": "^3.1.1"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"entities": {
|
"dom-serializer": {
|
||||||
"version": "1.1.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.2.0",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domelementtype": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
|
||||||
|
},
|
||||||
|
"domutils": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-serializer": "^1.0.1",
|
||||||
|
"domelementtype": "^2.2.0",
|
||||||
|
"domhandler": "^4.2.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -12887,9 +12912,9 @@
|
||||||
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
|
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.35",
|
"version": "7.0.36",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
||||||
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==",
|
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
|
@ -14415,6 +14440,11 @@
|
||||||
"workbox-webpack-plugin": "5.1.4"
|
"workbox-webpack-plugin": "5.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-token-auth": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-token-auth/-/react-token-auth-1.1.8.tgz",
|
||||||
|
"integrity": "sha512-stS7VbLu57qTC4H2R0Cd7nxuhXeQ2oR3oanXf+sX46BTq6N3ecKfmgTDnfJ0ce+QNX4tWUSbgqMzEPDbkmp7KA=="
|
||||||
|
},
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||||
|
@ -14628,15 +14658,15 @@
|
||||||
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
|
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
|
||||||
},
|
},
|
||||||
"renderkid": {
|
"renderkid": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz",
|
||||||
"integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==",
|
"integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"css-select": "^2.0.2",
|
"css-select": "^4.1.3",
|
||||||
"dom-converter": "^0.2",
|
"dom-converter": "^0.2.0",
|
||||||
"htmlparser2": "^3.10.1",
|
"htmlparser2": "^6.1.0",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.21",
|
||||||
"strip-ansi": "^3.0.0"
|
"strip-ansi": "^3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
|
@ -14644,6 +14674,56 @@
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||||
},
|
},
|
||||||
|
"css-select": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
|
||||||
|
"requires": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-what": "^5.0.0",
|
||||||
|
"domhandler": "^4.2.0",
|
||||||
|
"domutils": "^2.6.0",
|
||||||
|
"nth-check": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"css-what": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg=="
|
||||||
|
},
|
||||||
|
"dom-serializer": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.2.0",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domelementtype": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
|
||||||
|
},
|
||||||
|
"domutils": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-serializer": "^1.0.1",
|
||||||
|
"domelementtype": "^2.2.0",
|
||||||
|
"domhandler": "^4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nth-check": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
|
||||||
|
"requires": {
|
||||||
|
"boolbase": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
|
"react-token-auth": "^1.1.8",
|
||||||
"web-vitals": "^1.1.1"
|
"web-vitals": "^1.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
11
frontend/src/auth/AuthProvider.js
Normal file
11
frontend/src/auth/AuthProvider.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { createAuthProvider } from "react-token-auth";
|
||||||
|
|
||||||
|
export const [useAuth, authFetch, login, logout] =
|
||||||
|
createAuthProvider({
|
||||||
|
accessTokenKey: 'access_token',
|
||||||
|
onUpdateToken: (token) => fetch('/api/refresh', {
|
||||||
|
method: 'POST',
|
||||||
|
body: token.access_token
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
})
|
|
@ -5,7 +5,7 @@ function InputField(props) {
|
||||||
return (
|
return (
|
||||||
<label className="input-field">
|
<label className="input-field">
|
||||||
<p>{props.LabelName}</p>
|
<p>{props.LabelName}</p>
|
||||||
<input name={props.InputName} type={props.InputType} />
|
<input name={props.InputName} onChange={props.onChange} type={props.InputType} />
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ function SubmitField(props) {
|
||||||
const InputValue = props.LabelName;
|
const InputValue = props.LabelName;
|
||||||
return (
|
return (
|
||||||
<label className="input-field" className="btn btn--primary btn--medium">
|
<label className="input-field" className="btn btn--primary btn--medium">
|
||||||
<input type="submit" value={InputValue} />
|
<input type="submit" onClick={props.onClick} value={InputValue} />
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from "react";
|
||||||
import "../../App.css";
|
import "../../App.css";
|
||||||
import HeroSection from "../HeroSection";
|
import HeroSection from "../HeroSection";
|
||||||
import Footer from "../../Footer";
|
import Footer from "../../Footer";
|
||||||
|
import { useEffect } from "react/cjs/react.development";
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,28 +1,72 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useState, useEffect } from "react/cjs/react.development";
|
||||||
import "../../App.css";
|
import "../../App.css";
|
||||||
import Footer from "../../Footer";
|
import Footer from "../../Footer";
|
||||||
import InputField from "../InputField";
|
import InputField from "../InputField";
|
||||||
import SubmitField from "../SubmitField";
|
import SubmitField from "../SubmitField";
|
||||||
|
import { login, useAuth, logout } from "../../auth/AuthProvider";
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
|
const [username, setUsername] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
|
||||||
|
const onSubmitClick = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("You pressed login");
|
||||||
|
let opts = {
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
};
|
||||||
|
console.log(opts);
|
||||||
|
fetch("/api/login", {
|
||||||
|
method: "post",
|
||||||
|
body: JSON.stringify(opts),
|
||||||
|
})
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((token) => {
|
||||||
|
if (token.access_token) {
|
||||||
|
login(token);
|
||||||
|
console.log(token);
|
||||||
|
} else {
|
||||||
|
console.log("Please type in the correct username / password");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUsernameChange = (e) => {
|
||||||
|
setUsername(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePasswordChange = (e) => {
|
||||||
|
setPassword(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [logged] = useAuth();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="sitePage">
|
<div className="sitePage">
|
||||||
<h1>Login</h1>
|
<h1>Login</h1>
|
||||||
<form>
|
{!logged ? (
|
||||||
<InputField
|
<form action="#">
|
||||||
LabelName="Benutzername / Kennung"
|
<InputField
|
||||||
InputType=""
|
LabelName="Benutzername / Kennung"
|
||||||
InputName="username"
|
onChange={handleUsernameChange}
|
||||||
/>
|
InputType="text"
|
||||||
<InputField
|
InputName="username"
|
||||||
LabelName="Passwort"
|
/>
|
||||||
InputType="password"
|
<InputField
|
||||||
InputName="password"
|
LabelName="Passwort"
|
||||||
/>
|
InputType="password"
|
||||||
<br />
|
onChange={handlePasswordChange}
|
||||||
<SubmitField LabelName="Einloggen" />
|
InputName="password"
|
||||||
</form>
|
/>
|
||||||
|
<br />
|
||||||
|
<SubmitField onClick={onSubmitClick} LabelName="Einloggen" />
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<button onClick={() => logout()}>Logout</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in a new issue