Third party apps portal (#3782)
* Added third party apps portal page stub * [WIP] third party apps portal page * Added portal page third party apps Added page to manage OAuth 2.0 active sessions * [Fix] Typo me.html * frappe/www/third_party_apps. * [Fix] Added column for last log in
This commit is contained in:
parent
377f233ca4
commit
d56fbaba41
4 changed files with 132 additions and 2 deletions
|
|
@ -0,0 +1,9 @@
|
|||
frappe.ready(() => {
|
||||
$(".btn-delete-app").on("click", function(event) {
|
||||
frappe.call({
|
||||
method:"frappe.www.third_party_apps.delete_client",
|
||||
args: {"client_id": $(this).data("client_id"),
|
||||
}
|
||||
}).done(r => location.href="/third_party_apps");
|
||||
});
|
||||
});
|
||||
|
|
@ -18,10 +18,12 @@
|
|||
<li><a href="/update-password">
|
||||
<h6 class="text-muted">{{ _("Reset Password") }}</h6>
|
||||
</a></li>
|
||||
<li><a href="/update-profile?name={{ user }}">
|
||||
<li><a href="/update-profile?name={{ user }}">
|
||||
<h6 class="text-muted">{{ _("Edit Profile") }}</h6>
|
||||
</a></li>
|
||||
|
||||
<li><a href="/third_party_apps">
|
||||
<h6 class="text-muted">{{ _("Manage Third Party Apps") }}</h6>
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
66
frappe/www/third_party_apps.html
Normal file
66
frappe/www/third_party_apps.html
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block title %} {{ _("Third Party Apps") }} {% endblock %}
|
||||
{% block header %}
|
||||
<h1>{{ _("Third Party Apps") }}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_sidebar %}
|
||||
{% include "templates/pages/web_sidebar.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block style %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<!-- no-cache -->
|
||||
|
||||
<div class='padding'></div>
|
||||
|
||||
{% if app %}
|
||||
<h4>{{ app.app_name }}</h4>
|
||||
<div class="web-list-item">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="well">
|
||||
<div class="text-muted">{{ _("This will log out {0} from all other devices".format(app.app_name)) }}</div>
|
||||
<div class="padding"></div>
|
||||
<div class="text-right">
|
||||
<button class="btn btn-default" onclick="location.href = '/third_party_apps';">Cancel</button>
|
||||
<button class="btn btn-danger btn-delete-app" data-client_id="{{ app.client_id }}">Revoke</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% elif apps|length > 0 %}
|
||||
<h4>{{ _("Active Sessions") }}</h4>
|
||||
{% for app in apps %}
|
||||
<div class="web-list-item">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
{{ app.app_name }}
|
||||
</div>
|
||||
<div class="col-xs-4 text-right text-muted">
|
||||
<small class="text-right">
|
||||
{{ _("logged in") }} {{ frappe.utils.pretty_date(app.creation) }}
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-xs-2 text-right small text-muted">
|
||||
<a class="btn btn-xs btn-link" href="/third_party_apps?app={{ app.name }}">{{ _("Revoke") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="text-center text-muted">
|
||||
{{ _("No Active Sessions")}}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="padding"></div>
|
||||
<script>
|
||||
{% include "templates/includes/integrations/third_party_apps.js" %}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
53
frappe/www/third_party_apps.py
Normal file
53
frappe/www/third_party_apps.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
import frappe.www.list
|
||||
|
||||
no_cache = 1
|
||||
no_sitemap = 1
|
||||
|
||||
def get_context(context):
|
||||
if frappe.session.user == 'Guest':
|
||||
frappe.throw(_("You need to be logged in to access this page"), frappe.PermissionError)
|
||||
|
||||
active_tokens = frappe.get_all("OAuth Bearer Token",
|
||||
filters=[["user", "=", frappe.session.user]],
|
||||
fields=["client"], distinct=True, order_by="creation")
|
||||
|
||||
client_apps = []
|
||||
|
||||
for token in active_tokens:
|
||||
creation = get_first_login(token.client)
|
||||
app = {
|
||||
"name": token.get("client"),
|
||||
"app_name": frappe.db.get_value("OAuth Client", token.get("client"), "app_name"),
|
||||
"creation": creation
|
||||
}
|
||||
client_apps.append(app)
|
||||
|
||||
app = None
|
||||
if (frappe.form_dict.has_key("app")):
|
||||
app = frappe.get_doc("OAuth Client", frappe.form_dict.app)
|
||||
app = app.__dict__
|
||||
app["client_secret"] = None
|
||||
|
||||
if app:
|
||||
context.app = app
|
||||
|
||||
context.apps = client_apps
|
||||
context.show_sidebar = True
|
||||
|
||||
def get_first_login(client):
|
||||
login_date = frappe.get_all("OAuth Bearer Token",
|
||||
filters=[["user", "=", frappe.session.user], ["client", "=", client]],
|
||||
fields=["creation"], order_by="creation", limit=1)
|
||||
|
||||
login_date = login_date[0].get("creation") if login_date and len(login_date) > 0 else None
|
||||
|
||||
return login_date
|
||||
|
||||
@frappe.whitelist()
|
||||
def delete_client(client_id):
|
||||
active_client_id_tokens = frappe.get_all("OAuth Bearer Token", filters=[["user", "=", frappe.session.user], ["client","=", client_id]])
|
||||
for token in active_client_id_tokens:
|
||||
frappe.delete_doc("OAuth Bearer Token", token.get("name"), ignore_permissions=True)
|
||||
Loading…
Add table
Reference in a new issue