update dependencies
[websub-hub] / src / template / template-helper.js
1 'use strict';
2
3 const { TemplateHelper } = require('@squeep/html-template-helper');
4 const { Message } = require('../enum');
5
6 /**
7 * Render a topic as a row of details.
8 * @param {Object} topic
9 * @param {Object[]} subscribers
10 * @param {Boolean} detailsLink
11 * @returns {String}
12 */
13 function renderTopicRow(topic, subscribers, detailsLink = true) {
14 if (!topic) {
15 return `<tr>
16 <th colspan="15">(topic not found)</th>
17 </tr>`;
18 }
19 return `<tr>
20 <th scope="row">${detailsLink ? '<a href="topic/' + topic.id + '">' : ''}${topic.url}${detailsLink ? '</a>' : ''}</th>
21 <td>${subscribers.length}</td>
22 <td>${TemplateHelper.dateFormat(topic.created, Message.EndOfTime, Message.BeginningOfTime, Message.Unknown)}</td>
23 <td>${TemplateHelper.secondsToPeriod(topic.leaseSecondsPreferred)}</td>
24 <td>${TemplateHelper.secondsToPeriod(topic.leaseSecondsMin)}</td>
25 <td>${TemplateHelper.secondsToPeriod(topic.leaseSecondsMax)}</td>
26 <td>${topic.publisherValidationUrl ? topic.publisherValidationUrl : 'None'}</td>
27 <td>${topic.isActive}</td>
28 <td>${topic.isDeleted}</td>
29 <td>${TemplateHelper.dateFormat(topic.lastPublish, Message.EndOfTime, Message.Never, Message.Never)}</td>
30 <td>${TemplateHelper.dateFormat(topic.contentFetchNextAttempt, Message.NextPublish, Message.Pending, Message.NextPublish)}</td>
31 <td>${topic.contentFetchAttemptsSinceSuccess}</td>
32 <td>${TemplateHelper.dateFormat(topic.contentUpdated, Message.EndOfTime, Message.Never, Message.Never)}</td>
33 <td>${topic.contentType}</td>
34 <td>${topic.id}</td>
35 </tr>`;
36 }
37
38
39 /**
40 * Render the header row for topic details.
41 * @returns {String}
42 */
43 function renderTopicRowHeader() {
44 return `<tr>
45 <th scope="col">Topic URL</th>
46 <th scope="col">Subscribers</th>
47 <th scope="col">Created</th>
48 <th scope="col">Lease Time Preferred</th>
49 <th scope="col">Lease Time Minimum</th>
50 <th scope="col">Lease Time Maximum</th>
51 <th scope="col">Publisher Validation URL</th>
52 <th scope="col">Active</th>
53 <th scope="col">Deleted</th>
54 <th scope="col">Last Publish Notification</th>
55 <th scope="col">Next Content Fetch</th>
56 <th scope="col">Content Fetch Failures</th>
57 <th scope="col">Content Updated</th>
58 <th scope="col">Content Type</th>
59 <th scope="col">Internal Id</th>
60 </tr>`;
61 }
62
63
64 /**
65 * Render a subscription as a row of details.
66 * @param {Object} subscription
67 * @returns {String}
68 */
69 function renderSubscriptionRow(subscription) {
70 if (!subscription) {
71 return `<tr>
72 <th colspan="12">(topic not found)</th>
73 </tr>`;
74 }
75 return `<tr>
76 <td scope="row">${subscription.callback}</td>
77 <td>${TemplateHelper.dateFormat(subscription.created, Message.EndOfTime, Message.BeginningOfTime, Message.Unknown)}</td>
78 <td>${TemplateHelper.dateFormat(subscription.verified, Message.EndOfTime, Message.Never, Message.Never)}</td>
79 <td>${TemplateHelper.dateFormat(subscription.expires, Message.Never, Message.BeginningOfTime, Message.Never)}</td>
80 <td>${!!subscription.secret}</td>
81 <td>${subscription.signatureAlgorithm}</td>
82 <td>${subscription.httpRemoteAddr}</td>
83 <td>${subscription.httpFrom}</td>
84 <td>${TemplateHelper.dateFormat(subscription.contentDelivered, Message.EndOfTime, Message.Never, Message.Never)}</td>
85 <td>${subscription.deliveryAttemptsSinceSuccess}</td>
86 <td>${TemplateHelper.dateFormat(subscription.deliveryNextAttempt, Message.EndOfTime, Message.NextPublish, Message.NextPublish)}</td>
87 <td>${subscription.id}</td>
88 </tr>`;
89 }
90
91
92 /**
93 * Render a row of headers for subscription details.
94 * @returns {String}
95 */
96 function renderSubscriptionRowHeader() {
97 return `<tr>
98 <th scope="col">Callback URL</th>
99 <th scope="col">Created</th>
100 <th scope="col">Verified</th>
101 <th scope="col">Expires</th>
102 <th scope="col">Using Secret</th>
103 <th scope="col">Signature Type</th>
104 <th scope="col">Remote Address</th>
105 <th scope="col">From</th>
106 <th scope="col">Content Delivered</th>
107 <th scope="col">Content Delivery Failures</th>
108 <th scope="col">Next Delivery</th>
109 <th scope="col">Internal Id</th>
110 </tr>
111 `;
112 }
113
114
115 /**
116 * Escape some xml things in strings.
117 * @param {String} string
118 */
119 function xmlEscape(string) {
120 if (typeof string === 'number') {
121 return string;
122 }
123 if (typeof string !== 'string') {
124 return undefined;
125 }
126 // eslint-disable-next-line security/detect-object-injection
127 return string.replace(/[<>&'"]/, (c) => ({
128 '<': '&lt;',
129 '>': '&gt;',
130 '&': '&amp;',
131 '\'': '&apos;',
132 '"': '&quot;',
133 }[c]));
134 }
135
136 module.exports = Object.assign(Object.create(TemplateHelper), {
137 xmlEscape,
138 renderTopicRowHeader,
139 renderTopicRow,
140 renderSubscriptionRowHeader,
141 renderSubscriptionRow,
142 });