diff --git a/frappe/templates/includes/integrations/third_party_apps.js b/frappe/templates/includes/integrations/third_party_apps.js new file mode 100644 index 0000000000..fe75f23db9 --- /dev/null +++ b/frappe/templates/includes/integrations/third_party_apps.js @@ -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"); + }); +}); diff --git a/frappe/www/me.html b/frappe/www/me.html index 1397eb9437..593fefc012 100644 --- a/frappe/www/me.html +++ b/frappe/www/me.html @@ -18,10 +18,12 @@
  • {{ _("Reset Password") }}
  • -
  • +
  • {{ _("Edit Profile") }}
  • - +
  • +
    {{ _("Manage Third Party Apps") }}
    +
  • diff --git a/frappe/www/third_party_apps.html b/frappe/www/third_party_apps.html new file mode 100644 index 0000000000..baf62fa641 --- /dev/null +++ b/frappe/www/third_party_apps.html @@ -0,0 +1,66 @@ +{% extends "templates/web.html" %} + +{% block title %} {{ _("Third Party Apps") }} {% endblock %} +{% block header %} +

    {{ _("Third Party Apps") }}

    +{% endblock %} + +{% block page_sidebar %} +{% include "templates/pages/web_sidebar.html" %} +{% endblock %} + +{% block style %} +{% endblock %} + +{% block page_content %} + + + +
    + +{% if app %} +

    {{ app.app_name }}

    +
    +
    +
    +
    +
    {{ _("This will log out {0} from all other devices".format(app.app_name)) }}
    +
    +
    + + +
    +
    +
    +
    +
    +{% elif apps|length > 0 %} +

    {{ _("Active Sessions") }}

    + {% for app in apps %} +
    +
    +
    + {{ app.app_name }} +
    +
    + + {{ _("logged in") }} {{ frappe.utils.pretty_date(app.creation) }} + +
    + +
    +
    + {% endfor %} +{% else %} +
    + {{ _("No Active Sessions")}} +
    +{% endif %} +
    + + +{% endblock %} diff --git a/frappe/www/third_party_apps.py b/frappe/www/third_party_apps.py new file mode 100644 index 0000000000..b70f795948 --- /dev/null +++ b/frappe/www/third_party_apps.py @@ -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) \ No newline at end of file