From 6502f4a5dac3f8d97e1edd2e6efc39179c5e672d Mon Sep 17 00:00:00 2001 From: xangelo Date: Tue, 18 May 2021 17:07:43 -0400 Subject: [PATCH] display all authenticated apps for a user on their account page I added a new "Account" link in the header that allows users to view all the apps that they've approved on their armadietto server. It will prompt them to log in with their username/password and then it will display: - Their account name (username@host) - A table of all their approved apps, with info about what permissions it has --- lib/armadietto.js | 6 +++++ lib/assets/style.css | 13 ++++++++++ lib/controllers/users.js | 56 ++++++++++++++++++++++++++++++++++++++++ lib/views/account.html | 29 +++++++++++++++++++++ lib/views/layout.html | 1 + lib/views/login.html | 19 ++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 lib/views/account.html create mode 100644 lib/views/login.html diff --git a/lib/armadietto.js b/lib/armadietto.js index 0be3a7d6..d30c7998 100644 --- a/lib/armadietto.js +++ b/lib/armadietto.js @@ -153,6 +153,12 @@ class Armadietto { if (method === 'POST') return users.register(); } + if (uri.pathname === 'account') { + const users = new Users(this, req, res); + if (method === 'GET') return users.showLoginForm(); + if (method === 'POST') return users.showAccountPage(); + } + match = uri.pathname.match(/^storage\/([^/]+)(.*)$/); if (match) { const username = decodeURIComponent(match[1]).split('@')[0]; diff --git a/lib/assets/style.css b/lib/assets/style.css index f4f0173d..7b9fc699 100644 --- a/lib/assets/style.css +++ b/lib/assets/style.css @@ -120,3 +120,16 @@ th, td { input { font: 0.8em Open Sans, FreeSans, Helvetica, Arial, sans-serif; } +.deemphasize { + color: #a6a6a6; + font-size: 0.8em; +} +.favicon { + width: 32px; + height: 32px; + vertical-align: middle; +} + +.account-info td { + font-size: 0.8em; +} diff --git a/lib/controllers/users.js b/lib/controllers/users.js index 3c511694..a366175e 100644 --- a/lib/controllers/users.js +++ b/lib/controllers/users.js @@ -18,6 +18,62 @@ class Users extends Controller { this.renderHTML(409, 'signup.html', { params: this.params, error }); } } + + async showLoginForm () { + if (this.redirectToSSL()) return; + this.renderHTML(200, 'login.html', { params: this.params, error: null }); + } + + async showAccountPage () { + if (this.blockUnsecureRequest()) return; + + const expandedPermissions = { + 'r': 'Read', + 'w': 'Write' + }; + + try { + await this.server._store.authenticate(this.params); + const authData = await this.server._store.readAuth(this.params.username); + // this is a bit of a monster but it formats the somewhat unwieldy auth.json + // for a user into something that looks like: + // { + // "params": {"username": string}, + // "host": string, + // "sessions: [ + // "clientId": string, <- the url for the app as per the spec + // "permissions": [ + // { + // "folder": string, + // "permissions": ["Read", "Write"] <- the permission array may contain one/both + // } + // ] + // ] + // } + // + // We're doing this transform just to make it easier on the view side to + // iterate over things. + this.renderHTML(200, 'account.html', { + params: { username: this.params.username }, + host: this.getHost(), + sessions: authData.sessions ? Object.keys(authData.sessions).map(k => { + return { + clientId: authData.sessions[k].clientId, + permissions: Object.keys(authData.sessions[k].permissions).map(folder => { + return { + folder: folder, + permissions: Object.keys(authData.sessions[k].permissions[folder]).filter(perm => { + return authData.sessions[k].permissions[folder][perm]; + }).map(v => expandedPermissions[v]) + }; + }) + }; + }) : [] + }); + } catch (error) { + this.renderHTML(409, 'login.html', { params: this.params, error }); + } + } } module.exports = Users; diff --git a/lib/views/account.html b/lib/views/account.html new file mode 100644 index 00000000..b1f62065 --- /dev/null +++ b/lib/views/account.html @@ -0,0 +1,29 @@ +

Account Info

+ +

Your storage account: <%= params.username %>@<%= host %>

+ + + + + + + + + + <% sessions.forEach(function(session) { %> + + + + + <% }); %> + +
ApplicationPermissions
+ Favicon for <%= session.clientId %> + <%= session.clientId %> + + <% session.permissions.forEach(folder => { %> + <%= folder.folder %> + (<%= folder.permissions.join(', ') %>) + + <% }); %> +
diff --git a/lib/views/layout.html b/lib/views/layout.html index bfe1ea5b..e2d7ee64 100644 --- a/lib/views/layout.html +++ b/lib/views/layout.html @@ -15,6 +15,7 @@

Remote Storage <%= host %>

diff --git a/lib/views/login.html b/lib/views/login.html new file mode 100644 index 00000000..281476ee --- /dev/null +++ b/lib/views/login.html @@ -0,0 +1,19 @@ +

Log In

+ +
+ <% if (error) { %> +

<%= error.message %>

+ <% } %> + + + + + + + + + + +
+

+