changes to app_token

This commit is contained in:
tuxcoder 2023-10-22 19:45:37 +02:00
parent 5bda9e8d83
commit 4498be544b
7 changed files with 71 additions and 85 deletions

View file

@ -35,6 +35,7 @@ class TOTPDeleteForm(FlaskForm):
class AppTokenForm(FlaskForm): class AppTokenForm(FlaskForm):
name = StringField(gettext('name'), validators=[DataRequired(),Length(min=1, max=255) ]) name = StringField(gettext('name'), validators=[DataRequired(),Length(min=1, max=255) ])
scopes = StringField(gettext('scopes'), validators=[DataRequired(),Length(min=1, max=255) ])
submit = SubmitField(gettext('Activate')) submit = SubmitField(gettext('Activate'))
class AppTokenDeleteForm(FlaskForm): class AppTokenDeleteForm(FlaskForm):

View file

@ -198,8 +198,12 @@ class User(BaseModel, ModelUpdatedMixin):
def change_password(self, password_new: str) -> None: def change_password(self, password_new: str) -> None:
self.password_hashed = crypt.crypt(password_new) self.password_hashed = crypt.crypt(password_new)
def get_tokens_by_service(self, service: Service) -> list['AppToken']: def get_token_by_name(self, name: str) -> Optional['AppToken']:
return [ token for token in self.app_tokens if token.service_name == service.name ] for token in self.app_tokens:
if token.name == name:
return token
return None
def get_token_by_scope(self, scope: str) -> Iterator['AppToken']: def get_token_by_scope(self, scope: str) -> Iterator['AppToken']:
for token in self.app_tokens: for token in self.app_tokens:

View file

@ -4,47 +4,36 @@
{% block content %} {% block content %}
<ul class="nav nav-tabs" id="myTab" role="tablist"> <div>
{% for service in services.values() if service.app_token %} <table class="table">
<li class="nav-item"> <thead>
<a class="nav-link{{' active' if loop.first else ''}}" id="home-tab" data-toggle="tab" href="#{{ service.name }}" role="tab" aria-controls="home" aria-selected="true">{{ service.name }}</a> <tr>
</li> <th>name</th>
{% endfor %} <th>scopes</th>
</ul> <th>last used</th>
<th>created at<th>
<div class="tab-content" id="myTabContent"> <th> <th>
{% for service in services.values() if service.app_token %} </tr>
</thead>
<div class="tab-pane fade{{ ' show active' if loop.first else '' }}" id="{{ service.name }}" role="tabpanel" aria-labelledby="{{ service.name }}-tab"> <tbody>
<table class="table"> {% for app_token in current_user.app_tokens %}
<thead> <tr>
<tr> <td>{{ app_token.name }}</td>
<th>name</th> <td>{{ app_token.scopes }}</td>
<th>last used</th> <td>{{ app_token.last_used }}</td>
<th>created at<th> <td>{{ app_token.created_at }}</td>
<th> <th> <td>
</tr> {{ render_form(delete_form, action_url=url_for('frontend.app_token_delete', app_token_name=app_token.name)) }}
</thead> {#
<tbody> <a title="{{ gettext('Revoke')}}" href="{{ url_for('.app_token_revoce', id=app_token.id) }}" onclick="client_cert.revoke_certificate(this.href, '{{ cert.serial_number_hex }}'); return false;"><i class="fas fa-ban"></i></a>
{% for app_token in current_user.get_tokens_by_service(service) %} #}
<tr> </td>
<td>{{ app_token.name }}</td> </tr>
<td>{{ app_token.last_used }}</td> {% endfor %}
<td>{{ app_token.created_at }}</td>
<td>
{{ render_form(delete_form, action_url=url_for('frontend.app_token_delete', service_name=service.name,app_token_name=app_token.name)) }}
{#
<a title="{{ gettext('Revoke')}}" href="{{ url_for('.app_token_revoce', id=app_token.id) }}" onclick="client_cert.revoke_certificate(this.href, '{{ cert.serial_number_hex }}'); return false;"><i class="fas fa-ban"></i></a>
#}
</td>
</tr>
{% endfor %}
</table> </table>
<a class="btn btn-primary" href="{{ url_for('frontend.app_token_new', service_name=service.name) }}"> <a class="btn btn-primary" href="{{ url_for('frontend.app_token_new') }}">
New Token New Token
</a> </a>
</div>
{% endfor %}
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,6 +1,6 @@
{% extends 'frontend/base.html.j2' %} {% extends 'frontend/base.html.j2' %}
{% block title %}{{ gettext('new app token for {service_name}').format(service_name=service.name) }}{% endblock %} {% block title %}{{ gettext('new app token') }}{% endblock %}
{% block content %} {% block content %}

View file

@ -1,12 +1,12 @@
{% extends 'frontend/base.html.j2' %} {% extends 'frontend/base.html.j2' %}
{% block title %}{{ gettext('new app token for {service_name}').format(service_name=service.name) }}{% endblock %} {% block title %}{{ gettext('new app token') }}{% endblock %}
{% block content %} {% block content %}
<div> <div>
<p> <p>
Your new App Token for {{ service.name }}: Your new App Token for scopes: {app_token.scopes}:
</p> </p>
<p> <p>

View file

@ -58,36 +58,36 @@ def introspect() -> ResponseReturnValue:
return jsonify(token_info) return jsonify(token_info)
@api_views.route('/login/<service_name>', methods=['POST']) # @api_views.route('/login/<service_name>', methods=['POST'])
def email_login(service_name: str) -> ResponseReturnValue: # def email_login(service_name: str) -> ResponseReturnValue:
if service_name not in lenticular_services: # if service_name not in lenticular_services:
return '', 404 # return '', 404
service = lenticular_services[service_name] # service = lenticular_services[service_name]
if not request.is_json: # if not request.is_json:
return jsonify({}), 400 # return jsonify({}), 400
req_payload = request.get_json() # type: Any # req_payload = request.get_json() # type: Any
if not isinstance(req_payload, dict): # if not isinstance(req_payload, dict):
return 'bad request', 400 # return 'bad request', 400
password = req_payload["password"] # password = req_payload["password"]
username = req_payload["username"] # username = req_payload["username"]
if '@' in username: # if '@' in username:
username = username.split('@')[0] # username = username.split('@')[0]
user = User.query.filter_by(username=username.lower()).first() # type: Optional[User] # user = User.query.filter_by(username=username.lower()).first() # type: Optional[User]
if user is None: # if user is None:
logger.warning(f'login with invalid username') # logger.warning(f'login with invalid username')
return jsonify({}), 403 # return jsonify({}), 403
for app_token in user.get_tokens_by_service(service): # for app_token in user.get_token_by_name(service):
if secrets.compare_digest(password, app_token.token): # if secrets.compare_digest(password, app_token.token):
app_token.last_used = datetime.now() # app_token.last_used = datetime.now()
db.session.commit() # db.session.commit()
return jsonify({'username': user.username}), 200 # return jsonify({'username': user.username}), 200
logger.warning(f'login with invalid password for {username}') # logger.warning(f'login with invalid password for {username}')
return jsonify({}), 403 # return jsonify({}), 403

View file

@ -153,17 +153,14 @@ def app_token() -> ResponseReturnValue:
delete_form=delete_form, delete_form=delete_form,
services=lenticular_services) services=lenticular_services)
@frontend_views.route('/app_token/<service_name>/new', methods=['GET','POST']) @frontend_views.route('/app_token/new', methods=['GET','POST'])
def app_token_new(service_name: str) -> ResponseReturnValue: def app_token_new() -> ResponseReturnValue:
if service_name not in lenticular_services:
return '', 404
service = lenticular_services[service_name]
form = AppTokenForm() form = AppTokenForm()
if form.validate_on_submit(): if form.validate_on_submit():
user_any = get_current_user() # type: Any user_any = get_current_user() # type: Any
user = user_any # type: User user = user_any # type: User
app_token = AppToken.new(user, service, "") app_token = AppToken.new(user, name="",scopes="")
form.populate_obj(app_token) form.populate_obj(app_token)
# check for duplicate names # check for duplicate names
for user_app_token in user.app_tokens: for user_app_token in user.app_tokens:
@ -171,23 +168,18 @@ def app_token_new(service_name: str) -> ResponseReturnValue:
return 'name already exist', 400 return 'name already exist', 400
user.app_tokens.append(app_token) user.app_tokens.append(app_token)
db.session.commit() db.session.commit()
return render_template('frontend/app_token_new_show.html.j2', service=service, app_token=app_token) return render_template('frontend/app_token_new_show.html.j2', app_token=app_token)
return render_template('frontend/app_token_new.html.j2', return render_template('frontend/app_token_new.html.j2',
form=form, form=form)
service=service)
@frontend_views.route('/app_token/<service_name>/<app_token_name>', methods=["POST"]) @frontend_views.route('/app_token/<app_token_name>', methods=["POST"])
def app_token_delete(service_name: str, app_token_name: str) -> ResponseReturnValue: def app_token_delete(app_token_name: str) -> ResponseReturnValue:
form = AppTokenDeleteForm() form = AppTokenDeleteForm()
if service_name not in lenticular_services:
return '', 404
service = lenticular_services[service_name]
if form.validate_on_submit(): if form.validate_on_submit():
app_token = get_current_user().get_token(service, app_token_name) app_token = get_current_user().get_token_by_name(app_token_name)
if app_token is None: if app_token is None:
return 'not found', 404 return 'not found', 404
db.session.delete(app_token) db.session.delete(app_token)