Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Approved App Listing (updated) #108

Merged
merged 11 commits into from
Jan 4, 2024
7 changes: 7 additions & 0 deletions lib/armadietto.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,14 @@ class Armadietto {
if (method === 'POST') return users.register();
}

if (pathname === 'account') {
const users = new Users(this, req, res);
if (method === 'GET') return users.showLoginForm();
if (method === 'POST') return users.showAccountPage();
}

match = pathname.match(/^storage\/([^/]+)(.*)$/);

if (match) {
const username = decodeURIComponent(match[1]).split('@')[0];
const path = match[2];
Expand Down
17 changes: 16 additions & 1 deletion lib/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ header.topbar nav ul {
padding: 0;
}

header.topbar .signup {
header.topbar .navitem {
display: inline-flex;
align-items: center;
gap: .125rem;
Expand All @@ -268,6 +268,7 @@ header.topbar .signup {
color: var(--arma-text-color);
transition: all .2s linear;
text-decoration: none;
height: 3rem;
}

header.topbar .signup::before {
Expand All @@ -277,6 +278,7 @@ header.topbar .signup::before {
}

header.topbar .signup:hover,
header.topbar .navitem:hover,
header.topbar .signup:focus {
color: var(--arma-text-color);
box-shadow: inset 0 0 0 .125rem var(--arma-text-color);
Expand Down Expand Up @@ -785,3 +787,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;
}
2 changes: 1 addition & 1 deletion lib/controllers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class Controller {
const headers = {
'Content-Length': html.length,
'Content-Type': 'text/html; charset=utf8',
'Content-Security-Policy': "sandbox allow-scripts allow-forms allow-same-origin; default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; object-src 'none'; child-src 'none'; connect-src 'none'; base-uri 'self'; frame-ancestors 'none';",
'Content-Security-Policy': "sandbox allow-scripts allow-forms allow-popups allow-same-origin; default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; object-src 'none'; child-src 'none'; connect-src 'none'; base-uri 'self'; frame-ancestors 'none';",
'X-Content-Type-Options': 'nosniff',
'Referrer-Policy': 'no-referrer'
};
Expand Down
59 changes: 59 additions & 0 deletions lib/controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,65 @@ 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.values(authData.sessions).map(session => {
return {
clientId: session.clientId,
appName: /https?:\/\/([a-zA-Z\d-]+)[.:$]/.exec(session.clientId)?.[1] || '',
permissions: Object.entries(session.permissions).map(([folder, perms]) => {
return {
folder,
permissions: Object.keys(perms).filter(perm => {
return perms[perm];
}).map(v => expandedPermissions[v])
};
})
};
})
: []
});
} catch (error) {
this.renderHTML(409, 'login.html', { params: this.params, error });
DougReeder marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

module.exports = Users;
31 changes: 31 additions & 0 deletions lib/views/account.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<section>
<header class="centered">
<h2>Account Info</h2>
<p>Your storage account: <%= params.username %>@<%= host %></p>
</header>

<table class="account-info">
<thead>
<tr>
<th>Application</th>
<th>Permissions</th>
</tr>
</thead>
<tbody>
<% sessions.forEach(function(session) { %>
<tr>
<td>
<a href="<%= session.clientId %>" target="_blank"><%= session.appName %></a>
</td>
<td>
<% session.permissions.forEach(folder => { %>
<%= folder.folder %> <span class="deemphasize">
(<%= folder.permissions.join(', ') %>)
</span>
<% }); %>
</td>
</tr>
<% }); %>
</tbody>
</table>
</section>
8 changes: 7 additions & 1 deletion lib/views/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,15 @@ <h1>

<nav role="navigation">
<ul>
<li>
<a class="navitem" href="<%= basePath %>/">Home</a>
</li>
<li>
<a class="navitem" href="<%= basePath %>/account">Account</a>
</li>
<% if (signup) { %>
<li class="login">
<a class="signup" href="<%= basePath %>/signup">Sign up</a>
<a class="navitem signup" href="<%= basePath %>/signup">Sign up</a>
</li>
<% } %>
<li>
Expand Down
23 changes: 23 additions & 0 deletions lib/views/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<section>
<header>
<h2>Log In</h2>
</header>

<form method="post" action="<%= basePath %>/account">
<% if (error) { %>
<p class="error"><%= error.message %></p>
<% } %>

<table>
<tr>
<th scope="row"><label for="username">Username</label></th>
<td><input type="text" id="username" name="username" value="<%= params.username || '' %>"></td>
</tr>
<tr>
<th scope="row"><label for="password">Password</label></th>
<td><input type="password" id="password" name="password" value=""></td>
</tr>
</table>
<button type="submit" name="login" value="Go">Login</button>
</form>
</section>