added organization and improved layout
This commit is contained in:
parent
f9eadc3c5a
commit
652a406461
54
app.py
54
app.py
|
@ -10,10 +10,11 @@ from flask_security.models import fsqla_v2 as fsqla
|
||||||
from flask_security.forms import LoginForm, Required, PasswordField
|
from flask_security.forms import LoginForm, Required, PasswordField
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from door import Door
|
from door import Door
|
||||||
|
|
||||||
door = Door('10.10.21.2')
|
MQTT_BROKER = '10.10.21.2'
|
||||||
|
|
||||||
|
door = Door(MQTT_BROKER)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ app.config['SECURITY_PASSWORD_SALT'] = os.environ.get("SECURITY_PASSWORD_SALT",
|
||||||
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = ('username', 'email')
|
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = ('username', 'email')
|
||||||
|
|
||||||
|
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///admin.db'
|
||||||
# As of Flask-SQLAlchemy 2.4.0 it is easy to pass in options directly to the
|
# As of Flask-SQLAlchemy 2.4.0 it is easy to pass in options directly to the
|
||||||
# underlying engine. This option makes sure that DB connections from the
|
# underlying engine. This option makes sure that DB connections from the
|
||||||
# pool are still valid. Important for entire application since
|
# pool are still valid. Important for entire application since
|
||||||
|
@ -69,10 +70,11 @@ def validate_valid_thru_date(form, field):
|
||||||
class TokenForm(FlaskForm):
|
class TokenForm(FlaskForm):
|
||||||
name = StringField('Name', validators=[DataRequired()])
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
email = EmailField('E-Mail', validators=[DataRequired()])
|
email = EmailField('E-Mail', validators=[DataRequired()])
|
||||||
|
organization = StringField('Organization', validators=[DataRequired()])
|
||||||
limit_validity = BooleanField('Gültigkeit begrenzen?')
|
limit_validity = BooleanField('Gültigkeit begrenzen?')
|
||||||
valid_thru = DateField('Gültig bis', validators=[validate_valid_thru_date])
|
valid_thru = DateField('Gültig bis', validators=[validate_valid_thru_date])
|
||||||
active = BooleanField('Aktiv?')
|
active = BooleanField('Aktiv?')
|
||||||
dsgvo = BooleanField('Einwilligung DSGVO erfragt?', validators=[DataRequired()])
|
dsgvo = BooleanField('Einwilligung Nutzungsbedingungen erfragt?', validators=[DataRequired()])
|
||||||
|
|
||||||
|
|
||||||
# Create a user to test with
|
# Create a user to test with
|
||||||
|
@ -90,7 +92,7 @@ def door_lock():
|
||||||
|
|
||||||
|
|
||||||
@app.route('/tokens')
|
@app.route('/tokens')
|
||||||
#@auth_required()
|
@auth_required()
|
||||||
def list_tokens():
|
def list_tokens():
|
||||||
tokens = door.get_tokens()
|
tokens = door.get_tokens()
|
||||||
assigned_tokens = {t: data for t, data in tokens.items() if not data['inactive']}
|
assigned_tokens = {t: data for t, data in tokens.items() if not data['inactive']}
|
||||||
|
@ -99,7 +101,7 @@ def list_tokens():
|
||||||
|
|
||||||
|
|
||||||
@app.route('/register-token', methods=['GET', 'POST'])
|
@app.route('/register-token', methods=['GET', 'POST'])
|
||||||
#@auth_required()
|
@auth_required()
|
||||||
def register():
|
def register():
|
||||||
"""Register new token for locking and unlocking the door.
|
"""Register new token for locking and unlocking the door.
|
||||||
|
|
||||||
|
@ -120,6 +122,7 @@ def register():
|
||||||
session['token'] = door.get_most_recent_token()['token']
|
session['token'] = door.get_most_recent_token()['token']
|
||||||
session['name'] = form.name.data
|
session['name'] = form.name.data
|
||||||
session['email'] = form.email.data
|
session['email'] = form.email.data
|
||||||
|
session['organization'] = form.organization.data
|
||||||
if form.limit_validity.data:
|
if form.limit_validity.data:
|
||||||
session['valid_thru'] = form.valid_thru.data.isoformat()
|
session['valid_thru'] = form.valid_thru.data.isoformat()
|
||||||
else:
|
else:
|
||||||
|
@ -131,7 +134,7 @@ def register():
|
||||||
|
|
||||||
|
|
||||||
@app.route('/edit-token/<token>', methods=['GET', 'POST'])
|
@app.route('/edit-token/<token>', methods=['GET', 'POST'])
|
||||||
#@auth_required()
|
@auth_required()
|
||||||
def edit_token(token):
|
def edit_token(token):
|
||||||
"""Edit data in the token file (name, email, valid_thru date, active/inactive).
|
"""Edit data in the token file (name, email, valid_thru date, active/inactive).
|
||||||
|
|
||||||
|
@ -144,7 +147,7 @@ def edit_token(token):
|
||||||
token : str
|
token : str
|
||||||
The token for which data should be edited.
|
The token for which data should be edited.
|
||||||
"""
|
"""
|
||||||
form = TokenForm()
|
form = TokenForm(request.form)
|
||||||
form.dsgvo.validators = [] # we skip the validation of the DSGVO checkbox here because we assume the user agreed
|
form.dsgvo.validators = [] # we skip the validation of the DSGVO checkbox here because we assume the user agreed
|
||||||
# to it before
|
# to it before
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
|
@ -155,6 +158,8 @@ def edit_token(token):
|
||||||
form.active.data = not et['inactive']
|
form.active.data = not et['inactive']
|
||||||
form.name.data = et['name'] if et['name'] else ''
|
form.name.data = et['name'] if et['name'] else ''
|
||||||
form.email.data = et['email'] if et['email'] else ''
|
form.email.data = et['email'] if et['email'] else ''
|
||||||
|
form.organization.data = et['organization'] if et['organization'] else ''
|
||||||
|
|
||||||
# for the valid thru date we use today's date in case there is not valid date in the database
|
# for the valid thru date we use today's date in case there is not valid date in the database
|
||||||
try:
|
try:
|
||||||
form.valid_thru.data = date.fromisoformat(et['valid_thru'])
|
form.valid_thru.data = date.fromisoformat(et['valid_thru'])
|
||||||
|
@ -167,21 +172,26 @@ def edit_token(token):
|
||||||
# flash an error message if the route is accessed with an invalid token
|
# flash an error message if the route is accessed with an invalid token
|
||||||
flash(f'Ausgewaehlter Token {token} in Tokenfile nicht gefunden.')
|
flash(f'Ausgewaehlter Token {token} in Tokenfile nicht gefunden.')
|
||||||
return redirect('/tokens')
|
return redirect('/tokens')
|
||||||
elif request.method == 'POST' and form.validate():
|
elif request.method == 'POST':
|
||||||
# store data in session cookie
|
if form.validate():
|
||||||
session['token'] = token
|
# store data in session cookie
|
||||||
session['name'] = form.name.data
|
session['token'] = token
|
||||||
session['email'] = form.email.data
|
session['name'] = form.name.data
|
||||||
if form.limit_validity.data:
|
session['organization'] = form.organization.data
|
||||||
session['valid_thru'] = form.valid_thru.data.isoformat()
|
session['email'] = form.email.data
|
||||||
|
if form.limit_validity.data:
|
||||||
|
session['valid_thru'] = form.valid_thru.data.isoformat()
|
||||||
|
else:
|
||||||
|
session['valid_thru'] = ''
|
||||||
|
session['inactive'] = not form.active.data
|
||||||
|
return redirect(f'/store-token')
|
||||||
else:
|
else:
|
||||||
session['valid_thru'] = ''
|
return render_template('edit.html', token=token, form=form)
|
||||||
session['inactive'] = not form.active.data
|
|
||||||
return redirect(f'/store-token')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/store-token')
|
@app.route('/store-token')
|
||||||
#@auth_required()
|
@auth_required()
|
||||||
def store_token():
|
def store_token():
|
||||||
"""Store token to the token file on disk.
|
"""Store token to the token file on disk.
|
||||||
|
|
||||||
|
@ -194,13 +204,13 @@ def store_token():
|
||||||
'email': session['email'],
|
'email': session['email'],
|
||||||
'valid_thru': session['valid_thru'],
|
'valid_thru': session['valid_thru'],
|
||||||
'inactive': session['inactive'],
|
'inactive': session['inactive'],
|
||||||
'organization': 'test_org'}
|
'organization': session['organization']}
|
||||||
door.store_tokens(tokens)
|
door.store_tokens(tokens)
|
||||||
return redirect('/tokens')
|
return redirect('/tokens')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/delete-token', methods=['POST'])
|
@app.route('/delete-token', methods=['POST'])
|
||||||
#@auth_required()
|
@auth_required()
|
||||||
def delete_token():
|
def delete_token():
|
||||||
"""Delete the given token from the token file and store the new token file to disk
|
"""Delete the given token from the token file and store the new token file to disk
|
||||||
|
|
||||||
|
@ -218,7 +228,7 @@ def delete_token():
|
||||||
|
|
||||||
|
|
||||||
@app.route('/deactivate-token/<token>')
|
@app.route('/deactivate-token/<token>')
|
||||||
#@auth_required()
|
@auth_required()
|
||||||
def deactivate_token(token):
|
def deactivate_token(token):
|
||||||
"""Deactivate access for the given token. This updates the token file on disk.
|
"""Deactivate access for the given token. This updates the token file on disk.
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,39 @@
|
||||||
Token {{ token }} editieren:
|
Token {{ token }} editieren:
|
||||||
</p>
|
</p>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<p>{{ form.csrf_token }}
|
<table>
|
||||||
<p>{{ form.name.label }} {{ form.name(size=20) }}</p>
|
{{ form.csrf_token }}
|
||||||
<p>{{ form.email.label }} {{ form.email(size=20) }}</p>
|
<tr>
|
||||||
<p>{{ form.limit_validity.label }} {{ form.limit_validity() }}</p>
|
<td>{{ form.name.label }}</td>
|
||||||
|
<td>{{ form.name(size=20) }}</td>
|
||||||
<div id="valid_thru_dialog" {% if not form.limit_validity.data %}hidden{% endif %}>
|
</tr>
|
||||||
<p>{{ form.valid_thru.label }} {{ form.valid_thru() }}</p>
|
<tr>
|
||||||
</div>
|
<td>{{ form.email.label }}</td>
|
||||||
<p>{{ form.active.label }} {{ form.active() }}</p>
|
<td>{{ form.email(size=20) }}</td>
|
||||||
|
</tr>
|
||||||
<input type="submit" value="Speichern">
|
<tr>
|
||||||
|
<td>{{ form.organization.label }}</td>
|
||||||
|
<td>{{ form.organization(size=20) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ form.limit_validity.label }}</td>
|
||||||
|
<td> {{ form.limit_validity() }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="valid_thru_row" style="display: {% if form.limit_validity.data %}table-row{% else %}none{% endif %}">
|
||||||
|
<td>{{ form.valid_thru.label }} </td>
|
||||||
|
<td>{{ form.valid_thru() }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ form.active.label }}</td>
|
||||||
|
<td> {{ form.active() }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="Speichern">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -39,7 +61,12 @@
|
||||||
<script>
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
$("#limit_validity").on("click", function () {
|
$("#limit_validity").on("click", function () {
|
||||||
$("#valid_thru_dialog").toggle(this.checked);
|
if (this.checked) {
|
||||||
|
$("#valid_thru_row").css("display", "table-row")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#valid_thru_row").css("display", "none")
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,15 +25,40 @@
|
||||||
RaumnutzerIn registrieren:
|
RaumnutzerIn registrieren:
|
||||||
</p>
|
</p>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<p>{{ form.csrf_token }}
|
<table>
|
||||||
<p>{{ form.name.label }} {{ form.name(size=20) }}</p>
|
{{ form.csrf_token }}
|
||||||
<p>{{ form.email.label }} {{ form.email(size=20) }}</p>
|
<tr>
|
||||||
<p>{{ form.limit_validity.label }} {{ form.limit_validity() }}</p>
|
<td>{{ form.name.label }}</td>
|
||||||
<div id="valid_thru_dialog" {% if not form.limit_validity.data %}hidden{% endif %}>
|
<td>{{ form.name(size=20) }}</td>
|
||||||
<p>{{ form.valid_thru.label }} {{ form.valid_thru() }}</p>
|
</tr>
|
||||||
</div>
|
<tr>
|
||||||
<p>{{ form.dsgvo.label }} {{ form.dsgvo() }}</p>
|
<td>{{ form.email.label }}</td>
|
||||||
<input type="submit" value="Abschicken">
|
<td>{{ form.email(size=20) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ form.organization.label }}</td>
|
||||||
|
<td>{{ form.organization(size=20) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ form.limit_validity.label }}</td>
|
||||||
|
<td> {{ form.limit_validity() }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="valid_thru_row" style="display: none">
|
||||||
|
<td>{{ form.valid_thru.label }} </td>
|
||||||
|
<td>{{ form.valid_thru() }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ form.dsgvo.label }} </td>
|
||||||
|
<td> {{ form.dsgvo() }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="Abschicken">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -44,7 +69,12 @@
|
||||||
<script>
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
$("#limit_validity").on("click", function () {
|
$("#limit_validity").on("click", function () {
|
||||||
$("#valid_thru_dialog").toggle(this.checked);
|
if (this.checked) {
|
||||||
|
$("#valid_thru_row").css("display", "table-row")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#valid_thru_row").css("display", "none")
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user