diff --git a/lib/armadietto.js b/lib/armadietto.js index 4cb2e378..454b84c5 100644 --- a/lib/armadietto.js +++ b/lib/armadietto.js @@ -195,6 +195,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 3d63e270..55af079f 100644 --- a/lib/assets/style.css +++ b/lib/assets/style.css @@ -785,3 +785,16 @@ button[name="deny"]:focus { #switch.light::before { content: url('sprite.svg#icon-moon'); } +.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 65ccf8c7..f9949995 100644 --- a/lib/controllers/users.js +++ b/lib/controllers/users.js @@ -27,6 +27,62 @@ class Users extends Controller { }); } } + + 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 fd353267..22c3f2b7 100644 --- a/lib/views/layout.html +++ b/lib/views/layout.html @@ -32,6 +32,12 @@