75d7ce7f7475e957f2e8020d2943c476c130878a
[squeep-indie-auther] / src / template / admin-ticket-html.js
1 'use strict';
2
3 /**
4 * This renders the interface for submitting a ticket proffer to a third-party.
5 */
6
7 const th = require('./template-helper');
8 const { sessionNavLinks } = require('@squeep/authentication-module');
9
10
11 /**
12 *
13 * @param {string} profile profile
14 * @returns {string} option
15 */
16 function renderProfileOption(profile) {
17 return `<option value="${profile}">${profile}</option>`;
18 }
19
20 /**
21 *
22 * @param {string} scope scope
23 * @returns {string} tr
24 */
25 function renderScopeCheckboxTR(scope) {
26 const defaultChecked = ['read'];
27 const checked = defaultChecked.includes(scope) ? ' checked' : '';
28 return `<tr class="scope">
29 \t<td><input type="checkbox" id="scopes-${scope}" name="scopes[]" value="${scope}"${checked}></td>
30 \t<td>${scope}</td>
31 </tr>`;
32 }
33
34 /**
35 *
36 * @param {object} ctx context
37 * @returns {string} section
38 */
39 function mainContent(ctx) {
40 const profileOptions = th.indented(4, (ctx?.profilesScopes?.profiles || []).map((profile) => renderProfileOption(profile)))
41 .join('\n');
42 const elideScopes = ['profile', 'email'];
43 const allScopes = Object.keys(ctx?.profilesScopes?.scopeIndex || {});
44 const displayScopes = (allScopes).filter((scope) => !elideScopes.includes(scope));
45 const scopesCheckboxRows = th.indented(5, displayScopes.map((scope) => renderScopeCheckboxTR(scope)))
46 .join('\n');
47 return `<section>
48 \t<form method="POST">
49 \t\t<div>
50 \t\t\tYou may proactively send a ticket to a third-party site,
51 \t\t\twhich they may redeem for an access token which grants additional
52 \t\t\taccess to the specified resource.
53 \t\t</div>
54 \t\t<br>
55 \t\t<fieldset>
56 \t\t\t<legend>Proffer A Ticket</legend>
57 \t\t\t<label for="profile-select">Profile Granting this Ticket</label>
58 \t\t\t<select id="profile-select" name="profile">
59 ${profileOptions}
60 \t\t\t</select>
61 \t\t\t<br>
62 \t\t\t<label for="resource-url">Resource URL:</label>
63 \t\t\t<input type="url" id="resource-url" name="resource" size="96">
64 \t\t\t<br>
65 \t\t\t<label for="recipient-url">Recipient URL:</label>
66 \t\t\t<input type="url" id="recipient-url" name="subject" size="96">
67 \t\t\t<br>
68 <fieldset>
69 <legend>Scopes</legend>
70 \t\t\t<table>
71 \t\t\t\t<tbody>
72 ${scopesCheckboxRows}
73 \t\t\t\t</tbody>
74 \t\t\t</table>
75 </fieldset>
76 \t\t\t<br>
77 \t\t\t<label for="scopes-adhoc">Additional Scopes (space separated):</label>
78 \t\t\t<input type="text" id="scopes-adhoc" name="adhoc" size="96">
79 \t\t\t<br>
80 \t\t\t<button type="submit" name="action" value="proffer-ticket">Send Ticket</button>
81 \t\t</fieldset>
82 \t</form>
83 </section>`;
84 }
85
86
87 /**
88 *
89 * @param {object} ctx context
90 * @param {object} ctx.profilesScopes.scopeIndex scopes structure
91 * @param {string[]} ctx.profileScopes.profiles profile
92 * @param {object} options options
93 * @param {object} options.manager manager options
94 * @param {string} options.manager.pageTitle page title
95 * @param {string} options.manager.logoUrl logo url
96 * @param {string[]} options.manager.footerEntries footer entries
97 * @returns {string} page
98 */
99 module.exports = (ctx, options) => {
100 const pagePathLevel = 1;
101 const htmlOptions = {
102 pageIdentifier: 'ticketProffer',
103 pageTitle: options.manager.pageTitle + ' - Ticket Proffer',
104 logoUrl: options.manager.logoUrl,
105 footerEntries: options.manager.footerEntries,
106 errorContent: ['Unable to send ticket.'],
107 };
108 th.navLinks(pagePathLevel, ctx, htmlOptions);
109 sessionNavLinks(pagePathLevel, ctx, htmlOptions);
110 const content = [
111 mainContent(ctx),
112 ];
113 return th.htmlPage(pagePathLevel, ctx, htmlOptions, content);
114 };