Token list and auth code list views

This commit is contained in:
Éloi Rivard 2020-08-26 16:27:08 +02:00
parent d94f7a4988
commit f2da1e87db
13 changed files with 227 additions and 3 deletions

View file

@ -144,6 +144,26 @@ def client(app, slapd_connection):
return c
@pytest.fixture
def authorization(app, slapd_connection):
a = AuthorizationCode(
oauthCode="my-code",
oauthClientID="client-id",
oauthSubject="user-id",
oauthRedirectURI="https://foo.bar/callback",
oauthResponseType="code",
oauthScope="openid profile",
oauthNonce="nonce",
oauthAuthorizationDate="20200101000000Z",
oauthAuthorizationLifetime="3600",
oauthCodeChallenge="challenge",
oauthCodeChallengeMethod="method",
oauthRevoked="FALSE",
)
a.save(slapd_connection)
return a
@pytest.fixture
def user(app, slapd_connection):
u = User(

17
tests/test_code_admin.py Normal file
View file

@ -0,0 +1,17 @@
def test_no_logged_no_access(testclient):
testclient.get("/authorization", status=403)
def test_no_admin_no_access(testclient, logged_user):
testclient.get("/authorization", status=403)
def test_authorizaton_list(testclient, authorization, logged_admin):
res = testclient.get("/authorization")
assert authorization.oauthCode in res.text
def test_authorizaton_view(testclient, authorization, logged_admin):
res = testclient.get("/authorization/" + authorization.oauthCode)
for attr in authorization.may + authorization.must:
assert attr in res.text

17
tests/test_token_admin.py Normal file
View file

@ -0,0 +1,17 @@
def test_no_logged_no_access(testclient):
testclient.get("/token", status=403)
def test_no_admin_no_access(testclient, logged_user):
testclient.get("/token", status=403)
def test_token_list(testclient, token, logged_admin):
res = testclient.get("/token")
assert token.oauthAccessToken in res.text
def test_token_view(testclient, token, logged_admin):
res = testclient.get("/token/" + token.oauthAccessToken)
for attr in token.may + token.must:
assert attr in res.text

View file

@ -1,7 +1,7 @@
import ldap
import os
import toml
from . import routes, clients, oauth
from . import routes, clients, oauth, tokens, authorizations
from flask import Flask, g, request, render_template
from flask_babel import Babel
@ -38,6 +38,8 @@ def setup_app(app):
app.register_blueprint(routes.bp)
app.register_blueprint(oauth.bp, url_prefix="/oauth")
app.register_blueprint(clients.bp, url_prefix="/client")
app.register_blueprint(tokens.bp, url_prefix="/token")
app.register_blueprint(authorizations.bp, url_prefix="/authorization")
babel = Babel(app)

20
web/authorizations.py Normal file
View file

@ -0,0 +1,20 @@
from flask import Blueprint, render_template
from .models import AuthorizationCode
from .flaskutils import admin_needed
bp = Blueprint(__name__, "authorizations")
@bp.route("/")
@admin_needed()
def index():
authorizations = AuthorizationCode.filter()
return render_template("authorization_list.html", authorizations=authorizations)
@bp.route("/<authorization_id>", methods=["GET", "POST"])
@admin_needed()
def view(authorization_id):
authorization = AuthorizationCode.get(authorization_id)
return render_template("authorization_view.html", authorization=authorization)

View file

@ -143,6 +143,10 @@ class AuthorizationCode(LDAPObjectHelper, AuthorizationCodeMixin):
base = "ou=authorizations"
id = "oauthCode"
@property
def issue_date(self):
return datetime.datetime.strptime(self.oauthIssueDate, "%Y%m%d%H%M%SZ")
def get_redirect_uri(self):
return self.oauthRedirectURI
@ -175,6 +179,10 @@ class Token(LDAPObjectHelper, TokenMixin):
base = "ou=tokens"
id = "oauthAccessToken"
@property
def issue_date(self):
return datetime.datetime.strptime(self.oauthIssueDate, "%Y%m%d%H%M%SZ")
@property
def revoked(self):
return self.oauthRevoked in ("yes", "YES", 1, "on", "ON", "TRUE", "true")

View file

@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block style %}
<link href="/static/datatables/jquery.dataTables.min.css" rel="stylesheet">
<link href="/static/datatables/dataTables.semanticui.min.css" rel="stylesheet">
{% endblock %}
{% block script %}
<script src="/static/datatables/jquery.dataTables.min.js"></script>
<script src="/static/datatables/dataTables.semanticui.min.js"></script>
<script src="/static/js/users.js"></script>
{% endblock %}
{% block content %}
<table class="ui table">
<thead>
<th>{% trans %}Token{% endtrans %}</th>
<th>{% trans %}Client{% endtrans %}</th>
<th>{% trans %}Subject{% endtrans %}</th>
<th>{% trans %}Created{% endtrans %}</th>
</thead>
{% for authorization in authorizations %}
<tr>
<td><a href="{{ url_for('web.authorizations.view', authorization_id=authorization.oauthCode) }}">{{ authorization.oauthCode }}</a></td>
<td><a href="{{ url_for('web.clients.edit', client_id=authorization.oauthClientID) }}">{{ authorization.oauthClientID }}</a></td>
<td>{{ authorization.oauthSubject }}</td>
<td>{{ authorization.issue_date }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View file

@ -0,0 +1,27 @@
{% extends 'base.html' %}
{% import 'fomanticui.j2' as sui %}
{% block content %}
<div class="loginform">
<h3 class="ui top attached header">
{% trans %}View a authorization{% endtrans %}
</h3>
{% with messages = get_flashed_messages(with_categories=true) %}
{% for category, message in messages %}
<div class="ui attached message {{ category }}">
{{ message }}
</div>
{% endfor %}
{% endwith %}
<div class="ui attached clearing segment">
<ul>
{% for attr in authorization.may %}
<li>{{ attr }}: {{ authorization[attr] }}</li>
{% endfor %}
{% for attr in authorization.must %}
<li>{{ attr }}: {{ authorization[attr] }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}

View file

@ -37,11 +37,11 @@
<i class="plug icon"></i>
{% trans %}Clients{% endtrans %}
</a>
<a class="item" href="/">
<a class="item" href="{{ url_for('web.tokens.index') }}">
<i class="key icon"></i>
{% trans %}Tokens{% endtrans %}
</a>
<a class="item" href="/">
<a class="item" href="{{ url_for('web.authorizations.index') }}">
<i class="user secret icon"></i>
{% trans %}Codes{% endtrans %}
</a>

View file

@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block style %}
<link href="/static/datatables/jquery.dataTables.min.css" rel="stylesheet">
<link href="/static/datatables/dataTables.semanticui.min.css" rel="stylesheet">
{% endblock %}
{% block script %}
<script src="/static/datatables/jquery.dataTables.min.js"></script>
<script src="/static/datatables/dataTables.semanticui.min.js"></script>
<script src="/static/js/users.js"></script>
{% endblock %}
{% block content %}
<table class="ui table">
<thead>
<th>{% trans %}Token{% endtrans %}</th>
<th>{% trans %}Client{% endtrans %}</th>
<th>{% trans %}Subject{% endtrans %}</th>
<th>{% trans %}Created{% endtrans %}</th>
</thead>
{% for token in tokens %}
<tr>
<td><a href="{{ url_for('web.tokens.view', token_id=token.oauthAccessToken) }}">{{ token.oauthAccessToken }}</a></td>
<td><a href="{{ url_for('web.clients.edit', client_id=token.oauthClientID) }}">{{ token.oauthClientID }}</a></td>
<td>{{ token.oauthSubject }}</td>
<td>{{ token.issue_date }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View file

@ -0,0 +1,27 @@
{% extends 'base.html' %}
{% import 'fomanticui.j2' as sui %}
{% block content %}
<div class="loginform">
<h3 class="ui top attached header">
{% trans %}View a token{% endtrans %}
</h3>
{% with messages = get_flashed_messages(with_categories=true) %}
{% for category, message in messages %}
<div class="ui attached message {{ category }}">
{{ message }}
</div>
{% endfor %}
{% endwith %}
<div class="ui attached clearing segment">
<ul>
{% for attr in token.may %}
<li>{{ attr }}: {{ token[attr] }}</li>
{% endfor %}
{% for attr in token.must %}
<li>{{ attr }}: {{ token[attr] }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}

20
web/tokens.py Normal file
View file

@ -0,0 +1,20 @@
from flask import Blueprint, render_template
from .models import Token
from .flaskutils import admin_needed
bp = Blueprint(__name__, "tokens")
@bp.route("/")
@admin_needed()
def index():
tokens = Token.filter()
return render_template("token_list.html", tokens=tokens)
@bp.route("/<token_id>", methods=["GET", "POST"])
@admin_needed()
def view(token_id):
token = Token.get(token_id)
return render_template("token_view.html", token=token)