split client details into 3 pages: basic info, oauth settings, oauth endpoints

This commit is contained in:
Son NK 2019-08-16 12:03:45 +02:00
parent 28d475ea22
commit 1dd7a761fa
6 changed files with 312 additions and 186 deletions

View File

@ -1,180 +0,0 @@
{% extends 'default.html' %}
{% set active_page = "developer" %}
{% block title %}
Developer - Edit client
{% endblock %}
{% block default_content %}
<div class="col-md-8 offset-md-2">
<form method="post" enctype="multipart/form-data">
{{ form.csrf_token }}
<h3>App Info</h3>
<div class="form-group">
<label class="form-label">Display Name</label>
{{ form.name(class="form-control", value=client.name) }}
{{ render_field_errors(form.name) }}
</div>
{# <div class="form-group">#}
{# <label class="form-label">Website URL</label>#}
{# {{ form.home_url(class="form-control", type="url", value=client.home_url or "",#}
{# placeholder="https://mywebsite.com") }}#}
{# {{ render_field_errors(form.home_url) }}#}
{# </div>#}
<div class="form-group">
<div class="form-label">App Icon</div>
{{ form.icon(class="form-control-file") }}
{{ render_field_errors(form.icon) }}
{% if client.icon_id %}
<img src="{{ client.icon.get_url() }}" class="client-icon">
{% endif %}
</div>
<hr>
<h3>OpenID/OAuth2 parameters</h3>
<div class="form-group">
<label class="form-label">OAuth2 Client ID</label>
<div class="input-group mt-2">
<input disabled type="text" value="{{ client.oauth_client_id }}" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="{{ client.oauth_client_id }}"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">OAuth2 Client Secret</label>
<div class="input-group mt-2">
<input disabled type="password" value="{{ client.oauth_client_secret }}" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="{{ client.oauth_client_secret }}"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">Authorization endpoint</label>
<div class="input-group mt-2">
<input type="text" disabled value="https://app.simplelogin.io/oauth2/authorize" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="https://app.simplelogin.io/oauth2/authorize"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">Token endpoint</label>
<div class="input-group mt-2">
<input type="text" disabled value="https://app.simplelogin.io/oauth2/token" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="https://app.simplelogin.io/oauth2/token"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">UserInfo endpoint</label>
<div class="input-group mt-2">
<input type="text" disabled value="https://app.simplelogin.io/oauth2/userinfo" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="https://app.simplelogin.io/oauth2/userinfo"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">Authorized URIs</label>
{% for redirect_uri in client.redirect_uris %}
<div class="input-group mt-2">
<input type="url" name="uri" class="form-control" value="{{ redirect_uri.uri }}" required>
<span class="input-group-append">
<button class="remove-uri btn btn-primary" type="button">
<i class="fe fe-x"></i>
</button>
</span>
</div>
{% endfor %}
<div id="new-uris">
<!-- New uri will be put here -->
</div>
<button type="button" id="create-new-uri" class="mt-2 btn btn-secondary">Add new uri</button>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-lg">Update</button>
</form>
<!-- template for new uri -->
<div class="input-group mt-2" id="hidden-uri" style="display: none">
<input type="url" name="uri" class="form-control" required>
<span class="input-group-append">
<button class="remove-uri btn btn-primary" type="button">
<i class="fe fe-x"></i>
</button>
</span>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/x-template" id="course-detail">
<h1> ALO </h1>
</script>
<script>
$("#create-new-uri").on("click", function (e) {
var clone = $("#hidden-uri").clone(true, true); // (true, true) to clone withDataAndEvents, deepWithDataAndEvents
clone.removeAttr("id");
$("#new-uris").append(clone);
clone.show();
});
$(".remove-uri").click(function (e) {
var currentElement = $(this);
currentElement.parent().parent().remove();
});
</script>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends 'default.html' %}
{% set active_page = "developer" %}
{% block title %}
Developer - App {{ client.name }}
{% endblock %}
{% block default_content %}
<div class="row">
<div class="col-lg-3 order-lg-1 mb-4">
<a href="https://docs.simplelogin.io" class="btn btn-block btn-primary mb-6">
<i class="fe fe-github mr-2"></i>Browse Documentation
</a>
<div class="list-group list-group-transparent mb-0">
<a href="{{ url_for('developer.client_detail', client_id=client.id) }}"
class="list-group-item list-group-item-action {{ 'active' if client_details_page == 'basic_info' }}">
<span class="icon mr-3"><i class="fe fe-flag"></i></span>Basic Info
</a>
<a href="{{ url_for('developer.client_detail_oauth_setting', client_id=client.id) }}"
class="list-group-item list-group-item-action {{ 'active' if client_details_page == 'oauth_setting' }}">
<span class="icon mr-3"><i class="fe fe-settings"></i></span>OAuth Setting
</a>
<a href="{{ url_for('developer.client_detail_oauth_endpoint', client_id=client.id) }}"
class="list-group-item list-group-item-action {{ 'active' if client_details_page == 'oauth_endpoint' }}">
<span class="icon mr-3"><i class="fe fe-shield"></i></span>OAuth Endpoints
</a>
</div>
</div>
<div class="col-lg-9">
<div class="card">
<div class="card-body">
<div class="text-wrap p-lg-6">
{% block client_details_content %}
{% endblock %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,34 @@
{% extends 'developer/client_details/base.html' %}
{% set client_details_page = "basic_info" %}
{% block client_details_content %}
<form method="post" enctype="multipart/form-data">
{{ form.csrf_token }}
<h3>App Info</h3>
<div class="form-group">
<label class="form-label">Display Name</label>
{{ form.name(class="form-control", value=client.name) }}
{{ render_field_errors(form.name) }}
</div>
<div class="form-group">
<label class="form-label">Website URL</label>
{{ form.home_url(class="form-control", type="url", value=client.home_url or "",
placeholder="https://mywebsite.com") }}
{{ render_field_errors(form.home_url) }}
</div>
<div class="form-group">
<div class="form-label">App Icon</div>
{{ form.icon(class="form-control-file") }}
{{ render_field_errors(form.icon) }}
{% if client.icon_id %}
<img src="{{ client.icon.get_url() }}" class="client-icon">
{% endif %}
</div>
<button type="submit" class="btn btn-primary btn-lg">Update</button>
</form>
{% endblock %}

View File

@ -0,0 +1,53 @@
{% extends 'developer/client_details/base.html' %}
{% set client_details_page = "oauth_endpoint" %}
{% block client_details_content %}
<h3>OAuth2 endpoints</h3>
<div class="form-group">
<label class="form-label">Authorization endpoint</label>
<div class="input-group mt-2">
<input type="text" disabled value="https://app.simplelogin.io/oauth2/authorize" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="https://app.simplelogin.io/oauth2/authorize"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">Token endpoint</label>
<div class="input-group mt-2">
<input type="text" disabled value="https://app.simplelogin.io/oauth2/token" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="https://app.simplelogin.io/oauth2/token"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">UserInfo endpoint</label>
<div class="input-group mt-2">
<input type="text" disabled value="https://app.simplelogin.io/oauth2/userinfo" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="https://app.simplelogin.io/oauth2/userinfo"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,120 @@
{% extends 'developer/client_details/base.html' %}
{% set client_details_page = "oauth_setting" %}
{% block client_details_content %}
<form method="post">
{{ form.csrf_token }}
<h3>OAuth2 Settings</h3>
<div class="form-group">
<label class="form-label">OAuth2 Client ID</label>
<div class="input-group mt-2">
<input disabled type="text" value="{{ client.oauth_client_id }}" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="{{ client.oauth_client_id }}"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<div class="form-group">
<label class="form-label">OAuth2 Client Secret</label>
<div class="input-group mt-2">
<input disabled type="password" value="{{ client.oauth_client_secret }}" class="form-control">
<span class="input-group-append">
<button
data-clipboard-text="{{ client.oauth_client_secret }}"
class="clipboard btn btn-primary" type="button">
<i class="fe fe-clipboard"></i>
</button>
</span>
</div>
</div>
<hr>
<div class="form-group">
<div class="row">
<label class="form-label col">Authorized URIs</label>
<p class="col text-right">
<small class="text-muted">
<em>redirect_uri</em> must be <b>https</b> for security reason.
</small>
</p>
</div>
{% if not client.redirect_uris %}
<p><small class="text-muted">
You haven't added any <a href="https://www.oauth.com/oauth2-servers/redirect-uris/">redirect_uri</a>,
that is the url that will receive the <em>code</em> or <em>access-token</em> in OAuth2 flow.
<br>
By default, SimpleLogin whitelists <em>localhost</em> but you do
need to add your <em>redirect_uri</em> here once your website/app goes live.
<br>
Start by adding your first <em>redirect_uri</em> here 👇
</small></p>
{% endif %}
{% for redirect_uri in client.redirect_uris %}
<div class="input-group mt-2">
<input type="url" name="uri" class="form-control" value="{{ redirect_uri.uri }}"
required pattern="^https:\/\/.*"
title="redirect_uri must be https">
<span class="input-group-append">
<button class="remove-uri btn btn-primary" type="button">
<i class="fe fe-x"></i>
</button>
</span>
</div>
{% endfor %}
<div id="new-uris">
<!-- New uri will be put here -->
</div>
<button type="button" id="create-new-uri" class="mt-2 btn btn-secondary">Add new uri</button>
</div>
<button type="submit" class="btn btn-primary btn-lg">Update</button>
</form>
<!-- template for new uri -->
<div class="input-group mt-2" id="hidden-uri" style="display: none">
<input type="url" name="uri" class="form-control"
required pattern="^https:\/\/.*"
title="redirect_uri must be https">
<span class="input-group-append">
<button class="remove-uri btn btn-primary" type="button">
<i class="fe fe-x"></i>
</button>
</span>
</div>
{% endblock %}
{% block script %}
<script>
$("#create-new-uri").on("click", function (e) {
var clone = $("#hidden-uri").clone(true, true); // (true, true) to clone withDataAndEvents, deepWithDataAndEvents
clone.removeAttr("id");
$("#new-uris").append(clone);
clone.show();
});
$(".remove-uri").click(function (e) {
var currentElement = $(this);
currentElement.parent().parent().remove();
});
</script>
{% endblock %}

View File

@ -20,6 +20,7 @@ class EditClientForm(FlaskForm):
home_url = StringField("Home Url")
# basic info
@developer_bp.route("/clients/<client_id>", methods=["GET", "POST"])
@login_required
def client_detail(client_id):
@ -31,7 +32,7 @@ def client_detail(client_id):
return redirect(url_for("developer.index"))
if client.user_id != current_user.id:
flash("you cannot see this client", "warning")
flash("you cannot see this app", "warning")
return redirect(url_for("developer.index"))
if form.validate_on_submit():
@ -46,12 +47,41 @@ def client_detail(client_id):
s3.upload_from_bytesio(file_path, BytesIO(form.icon.data.read()))
db.session.commit()
db.session.flush()
LOG.d("upload file %s to s3", file)
client.icon_id = file.id
db.session.commit()
db.session.flush()
db.session.commit()
flash(f"{client.name} has been updated", "success")
return redirect(url_for("developer.client_detail", client_id=client.id))
return render_template(
"developer/client_details/basic_info.html", form=form, client=client
)
class OAuthSettingForm(FlaskForm):
pass
@developer_bp.route("/clients/<client_id>/oauth_setting", methods=["GET", "POST"])
@login_required
def client_detail_oauth_setting(client_id):
form = OAuthSettingForm()
client = Client.get(client_id)
if not client:
flash("no such app", "warning")
return redirect(url_for("developer.index"))
if client.user_id != current_user.id:
flash("you cannot see this app", "warning")
return redirect(url_for("developer.index"))
if form.validate_on_submit():
uris = request.form.getlist("uri")
# replace all uris. TODO: optimize this?
@ -63,8 +93,29 @@ def client_detail(client_id):
db.session.commit()
flash(f"client {client.name} has been updated", "success")
flash(f"{client.name} has been updated", "success")
return redirect(url_for("developer.client_detail", client_id=client.id))
return redirect(
url_for("developer.client_detail_oauth_setting", client_id=client.id)
)
return render_template("developer/client_detail.html", form=form, client=client)
return render_template(
"developer/client_details/oauth_setting.html", form=form, client=client
)
@developer_bp.route("/clients/<client_id>/oauth_endpoint", methods=["GET", "POST"])
@login_required
def client_detail_oauth_endpoint(client_id):
client = Client.get(client_id)
if not client:
flash("no such app", "warning")
return redirect(url_for("developer.index"))
if client.user_id != current_user.id:
flash("you cannot see this app", "warning")
return redirect(url_for("developer.index"))
return render_template(
"developer/client_details/oauth_endpoint.html", client=client
)