solid-server 5.6.9-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/.acl +10 -0
  2. package/.github/workflows/ci.yml +47 -0
  3. package/.nvmrc +1 -0
  4. package/.snyk +35 -0
  5. package/.well-known/.acl +15 -0
  6. package/CHANGELOG.md +198 -0
  7. package/CONTRIBUTING.md +139 -0
  8. package/CONTRIBUTORS.md +36 -0
  9. package/Dockerfile +22 -0
  10. package/LICENSE.md +23 -0
  11. package/README.md +453 -0
  12. package/bin/lib/cli-utils.js +85 -0
  13. package/bin/lib/cli.js +39 -0
  14. package/bin/lib/init.js +94 -0
  15. package/bin/lib/invalidUsernames.js +148 -0
  16. package/bin/lib/migrateLegacyResources.js +69 -0
  17. package/bin/lib/options.js +399 -0
  18. package/bin/lib/start.js +148 -0
  19. package/bin/lib/updateIndex.js +56 -0
  20. package/bin/solid +3 -0
  21. package/bin/solid-test +12 -0
  22. package/bin/solid.js +3 -0
  23. package/common/css/solid.css +58 -0
  24. package/common/fonts/glyphicons-halflings-regular.eot +0 -0
  25. package/common/fonts/glyphicons-halflings-regular.svg +288 -0
  26. package/common/fonts/glyphicons-halflings-regular.ttf +0 -0
  27. package/common/fonts/glyphicons-halflings-regular.woff +0 -0
  28. package/common/fonts/glyphicons-halflings-regular.woff2 +0 -0
  29. package/common/img/.gitkeep +0 -0
  30. package/common/js/auth-buttons.js +65 -0
  31. package/common/js/solid.js +454 -0
  32. package/common/well-known/security.txt +2 -0
  33. package/config/defaults.js +25 -0
  34. package/config/usernames-blacklist.json +4 -0
  35. package/config.json-default +22 -0
  36. package/default-templates/emails/delete-account.js +49 -0
  37. package/default-templates/emails/invalid-username.js +30 -0
  38. package/default-templates/emails/reset-password.js +49 -0
  39. package/default-templates/emails/welcome.js +39 -0
  40. package/default-templates/new-account/.acl +26 -0
  41. package/default-templates/new-account/.meta +5 -0
  42. package/default-templates/new-account/.meta.acl +25 -0
  43. package/default-templates/new-account/.well-known/.acl +19 -0
  44. package/default-templates/new-account/favicon.ico +0 -0
  45. package/default-templates/new-account/favicon.ico.acl +26 -0
  46. package/default-templates/new-account/inbox/.acl +26 -0
  47. package/default-templates/new-account/private/.acl +10 -0
  48. package/default-templates/new-account/profile/.acl +19 -0
  49. package/default-templates/new-account/profile/card$.ttl +25 -0
  50. package/default-templates/new-account/public/.acl +19 -0
  51. package/default-templates/new-account/robots.txt +3 -0
  52. package/default-templates/new-account/robots.txt.acl +26 -0
  53. package/default-templates/new-account/settings/.acl +20 -0
  54. package/default-templates/new-account/settings/prefs.ttl +15 -0
  55. package/default-templates/new-account/settings/privateTypeIndex.ttl +4 -0
  56. package/default-templates/new-account/settings/publicTypeIndex.ttl +4 -0
  57. package/default-templates/new-account/settings/publicTypeIndex.ttl.acl +25 -0
  58. package/default-templates/new-account/settings/serverSide.ttl.acl +13 -0
  59. package/default-templates/new-account/settings/serverSide.ttl.inactive +12 -0
  60. package/default-templates/server/.acl +10 -0
  61. package/default-templates/server/.well-known/.acl +15 -0
  62. package/default-templates/server/favicon.ico +0 -0
  63. package/default-templates/server/favicon.ico.acl +15 -0
  64. package/default-templates/server/index.html +55 -0
  65. package/default-templates/server/robots.txt +3 -0
  66. package/default-templates/server/robots.txt.acl +15 -0
  67. package/default-views/account/account-deleted.hbs +17 -0
  68. package/default-views/account/delete-confirm.hbs +51 -0
  69. package/default-views/account/delete-link-sent.hbs +17 -0
  70. package/default-views/account/delete.hbs +51 -0
  71. package/default-views/account/invalid-username.hbs +22 -0
  72. package/default-views/account/register-disabled.hbs +6 -0
  73. package/default-views/account/register-form.hbs +132 -0
  74. package/default-views/account/register.hbs +24 -0
  75. package/default-views/auth/auth-hidden-fields.hbs +8 -0
  76. package/default-views/auth/change-password.hbs +58 -0
  77. package/default-views/auth/goodbye.hbs +23 -0
  78. package/default-views/auth/login-required.hbs +34 -0
  79. package/default-views/auth/login-tls.hbs +11 -0
  80. package/default-views/auth/login-username-password.hbs +28 -0
  81. package/default-views/auth/login.hbs +55 -0
  82. package/default-views/auth/no-permission.hbs +29 -0
  83. package/default-views/auth/password-changed.hbs +27 -0
  84. package/default-views/auth/reset-link-sent.hbs +21 -0
  85. package/default-views/auth/reset-password.hbs +52 -0
  86. package/default-views/auth/sharing.hbs +49 -0
  87. package/default-views/shared/create-account.hbs +8 -0
  88. package/default-views/shared/error.hbs +5 -0
  89. package/docs/how-to-delete-your-account.md +56 -0
  90. package/docs/login-and-grant-access-to-application.md +32 -0
  91. package/examples/custom-error-handling.js +31 -0
  92. package/examples/ldp-with-webid.js +12 -0
  93. package/examples/simple-express-app.js +20 -0
  94. package/examples/simple-ldp-server.js +8 -0
  95. package/favicon.ico +0 -0
  96. package/favicon.ico.acl +15 -0
  97. package/index.html +48 -0
  98. package/index.js +3 -0
  99. package/lib/acl-checker.js +274 -0
  100. package/lib/api/accounts/user-accounts.js +88 -0
  101. package/lib/api/authn/force-user.js +21 -0
  102. package/lib/api/authn/index.js +5 -0
  103. package/lib/api/authn/webid-oidc.js +202 -0
  104. package/lib/api/authn/webid-tls.js +69 -0
  105. package/lib/api/index.js +6 -0
  106. package/lib/capability-discovery.js +54 -0
  107. package/lib/common/fs-utils.js +43 -0
  108. package/lib/common/template-utils.js +50 -0
  109. package/lib/common/user-utils.js +28 -0
  110. package/lib/create-app.js +322 -0
  111. package/lib/create-server.js +107 -0
  112. package/lib/debug.js +17 -0
  113. package/lib/handlers/allow.js +82 -0
  114. package/lib/handlers/auth-proxy.js +63 -0
  115. package/lib/handlers/copy.js +39 -0
  116. package/lib/handlers/cors-proxy.js +95 -0
  117. package/lib/handlers/delete.js +23 -0
  118. package/lib/handlers/error-pages.js +212 -0
  119. package/lib/handlers/get.js +219 -0
  120. package/lib/handlers/index.js +42 -0
  121. package/lib/handlers/options.js +33 -0
  122. package/lib/handlers/patch/n3-patch-parser.js +49 -0
  123. package/lib/handlers/patch/sparql-update-parser.js +16 -0
  124. package/lib/handlers/patch.js +203 -0
  125. package/lib/handlers/post.js +99 -0
  126. package/lib/handlers/put.js +56 -0
  127. package/lib/handlers/restrict-to-top-domain.js +13 -0
  128. package/lib/header.js +136 -0
  129. package/lib/http-error.js +34 -0
  130. package/lib/ldp-container.js +161 -0
  131. package/lib/ldp-copy.js +73 -0
  132. package/lib/ldp-middleware.js +32 -0
  133. package/lib/ldp.js +620 -0
  134. package/lib/lock.js +10 -0
  135. package/lib/metadata.js +10 -0
  136. package/lib/models/account-manager.js +603 -0
  137. package/lib/models/account-template.js +152 -0
  138. package/lib/models/authenticator.js +333 -0
  139. package/lib/models/oidc-manager.js +53 -0
  140. package/lib/models/solid-host.js +131 -0
  141. package/lib/models/user-account.js +112 -0
  142. package/lib/models/webid-tls-certificate.js +184 -0
  143. package/lib/payment-pointer-discovery.js +83 -0
  144. package/lib/requests/add-cert-request.js +138 -0
  145. package/lib/requests/auth-request.js +234 -0
  146. package/lib/requests/create-account-request.js +468 -0
  147. package/lib/requests/delete-account-confirm-request.js +170 -0
  148. package/lib/requests/delete-account-request.js +144 -0
  149. package/lib/requests/login-request.js +205 -0
  150. package/lib/requests/password-change-request.js +201 -0
  151. package/lib/requests/password-reset-email-request.js +199 -0
  152. package/lib/requests/sharing-request.js +259 -0
  153. package/lib/resource-mapper.js +198 -0
  154. package/lib/server-config.js +167 -0
  155. package/lib/services/blacklist-service.js +33 -0
  156. package/lib/services/email-service.js +162 -0
  157. package/lib/services/token-service.js +47 -0
  158. package/lib/utils.js +254 -0
  159. package/lib/webid/index.js +13 -0
  160. package/lib/webid/lib/get.js +27 -0
  161. package/lib/webid/lib/parse.js +12 -0
  162. package/lib/webid/tls/index.js +185 -0
  163. package/package.json +172 -0
  164. package/renovate.json +5 -0
  165. package/robots.txt +3 -0
  166. package/robots.txt.acl +15 -0
  167. package/static/account-recovery.html +78 -0
  168. package/static/popup-redirect.html +1 -0
  169. package/static/signup.html +108 -0
  170. package/static/signup.html.acl +14 -0
@@ -0,0 +1,454 @@
1
+ /* global owaspPasswordStrengthTest, TextEncoder, crypto, fetch */
2
+ (function () {
3
+ 'use strict'
4
+
5
+ const PasswordValidator = function (passwordField, repeatedPasswordField) {
6
+ if (
7
+ passwordField === null || passwordField === undefined ||
8
+ repeatedPasswordField === null || repeatedPasswordField === undefined
9
+ ) {
10
+ return
11
+ }
12
+
13
+ this.passwordField = passwordField
14
+ this.repeatedPasswordField = repeatedPasswordField
15
+
16
+ this.fetchDomNodes()
17
+ this.bindEvents()
18
+
19
+ this.currentStrengthLevel = 0
20
+ this.errors = []
21
+ }
22
+
23
+ const FEEDBACK_SUCCESS = 'success'
24
+ const FEEDBACK_WARNING = 'warning'
25
+ const FEEDBACK_ERROR = 'error'
26
+
27
+ const ICON_SUCCESS = 'glyphicon-ok'
28
+ const ICON_WARNING = 'glyphicon-warning-sign'
29
+ const ICON_ERROR = 'glyphicon-remove'
30
+
31
+ const VALIDATION_SUCCESS = 'has-success'
32
+ const VALIDATION_WARNING = 'has-warning'
33
+ const VALIDATION_ERROR = 'has-error'
34
+
35
+ const STRENGTH_PROGRESS_0 = 'progress-bar-danger level-0'
36
+ const STRENGTH_PROGRESS_1 = 'progress-bar-danger level-1'
37
+ const STRENGTH_PROGRESS_2 = 'progress-bar-warning level-2'
38
+ const STRENGTH_PROGRESS_3 = 'progress-bar-success level-3'
39
+ const STRENGTH_PROGRESS_4 = 'progress-bar-success level-4'
40
+
41
+ /**
42
+ * Prefetch all dom nodes at initialisation in order to gain time at execution since DOM manipulations
43
+ * are really time consuming
44
+ */
45
+ PasswordValidator.prototype.fetchDomNodes = function () {
46
+ this.form = this.passwordField.closest('form')
47
+
48
+ this.disablePasswordChecks = this.passwordField.classList.contains('disable-password-checks')
49
+
50
+ this.passwordGroup = this.passwordField.closest('.form-group')
51
+ this.passwordFeedback = this.passwordGroup.querySelector('.form-control-feedback')
52
+ this.passwordStrengthMeter = this.passwordGroup.querySelector('.progress-bar')
53
+ this.passwordHelpText = this.passwordGroup.querySelector('.help-block')
54
+
55
+ this.repeatedPasswordGroup = this.repeatedPasswordField.closest('.form-group')
56
+ this.repeatedPasswordFeedback = this.repeatedPasswordGroup.querySelector('.form-control-feedback')
57
+ }
58
+
59
+ PasswordValidator.prototype.bindEvents = function () {
60
+ this.passwordField.addEventListener('focus', this.resetPasswordFeedback.bind(this))
61
+ this.passwordField.addEventListener('keyup', this.instantFeedbackForPassword.bind(this))
62
+ this.repeatedPasswordField.addEventListener('keyup', this.validateRepeatedPassword.bind(this))
63
+ this.passwordField.addEventListener('blur', this.validatePassword.bind(this))
64
+ }
65
+
66
+ /**
67
+ * Events Listeners
68
+ */
69
+
70
+ PasswordValidator.prototype.resetPasswordFeedback = function () {
71
+ this.errors = []
72
+ this.resetValidation(this.passwordGroup)
73
+ this.resetFeedbackIcon(this.passwordFeedback)
74
+ if (!this.disablePasswordChecks) {
75
+ this.displayPasswordErrors()
76
+ this.instantFeedbackForPassword()
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Validate password on the fly to provide the user a visual strength meter
82
+ */
83
+ PasswordValidator.prototype.instantFeedbackForPassword = function () {
84
+ const passwordStrength = this.getPasswordStrength(this.passwordField.value)
85
+ const strengthLevel = this.getStrengthLevel(passwordStrength)
86
+
87
+ if (this.currentStrengthLevel === strengthLevel) {
88
+ return
89
+ }
90
+
91
+ this.currentStrengthLevel = strengthLevel
92
+
93
+ this.updateStrengthMeter()
94
+
95
+ if (this.repeatedPasswordField.value !== '') {
96
+ this.updateRepeatedPasswordFeedback()
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Validate password and display the error(s) message(s)
102
+ */
103
+ PasswordValidator.prototype.validatePassword = function () {
104
+ this.errors = []
105
+ const password = this.passwordField.value
106
+
107
+ if (!this.disablePasswordChecks) {
108
+ const passwordStrength = this.getPasswordStrength(password)
109
+ this.currentStrengthLevel = this.getStrengthLevel(passwordStrength)
110
+
111
+ if (passwordStrength.errors) {
112
+ this.addPasswordError(passwordStrength.errors)
113
+ }
114
+
115
+ this.checkLeakedPassword(password).then(this.handleLeakedPasswordResponse.bind(this))
116
+ }
117
+
118
+ this.setPasswordFeedback()
119
+ }
120
+
121
+ /**
122
+ * Validate the repeated password upon typing
123
+ */
124
+ PasswordValidator.prototype.validateRepeatedPassword = function () {
125
+ this.updateRepeatedPasswordFeedback()
126
+ }
127
+
128
+ /**
129
+ * User Feedback manipulators
130
+ */
131
+
132
+ /**
133
+ * Update the strength meter based on OWASP feedback
134
+ */
135
+ PasswordValidator.prototype.updateStrengthMeter = function () {
136
+ this.resetStrengthMeter()
137
+
138
+ this.passwordStrengthMeter.classList.add.apply(
139
+ this.passwordStrengthMeter.classList,
140
+ this.tokenize(this.getStrengthLevelProgressClass())
141
+ )
142
+ }
143
+
144
+ PasswordValidator.prototype.setPasswordFeedback = function () {
145
+ const feedback = this.getFeedbackFromLevel()
146
+ this.updateStrengthMeter()
147
+ this.displayPasswordErrors()
148
+ this.setFeedbackForField(feedback, this.passwordField)
149
+ }
150
+
151
+ /**
152
+ * Update the repeated password feedback icon and color
153
+ */
154
+ PasswordValidator.prototype.updateRepeatedPasswordFeedback = function () {
155
+ const feedback = this.checkPasswordFieldsEquality() ? FEEDBACK_SUCCESS : FEEDBACK_ERROR
156
+ this.setFeedbackForField(feedback, this.repeatedPasswordField)
157
+ }
158
+
159
+ /**
160
+ * Display the given feedback on the field
161
+ * @param {string} feedback success|error|warning
162
+ * @param {HTMLElement} field
163
+ */
164
+ PasswordValidator.prototype.setFeedbackForField = function (feedback, field) {
165
+ const formGroup = this.getFormGroupElementForField(field)
166
+ const visualFeedback = this.getFeedbackElementForField(field)
167
+
168
+ this.resetValidation(formGroup)
169
+ this.resetFeedbackIcon(visualFeedback)
170
+
171
+ visualFeedback.classList.remove('hidden')
172
+
173
+ visualFeedback.classList
174
+ .add
175
+ .apply(
176
+ visualFeedback.classList,
177
+ this.tokenize(this.getFeedbackIconClass(feedback))
178
+ )
179
+
180
+ formGroup.classList
181
+ .add
182
+ .apply(
183
+ formGroup.classList,
184
+ this.tokenize(this.getValidationClass(feedback))
185
+ )
186
+ }
187
+
188
+ /**
189
+ * Password Strength Helpers
190
+ */
191
+
192
+ /**
193
+ * Get OWASP feedback on the given password. Returns false if the password is empty
194
+ * @param password
195
+ * @returns {object|false}
196
+ */
197
+ PasswordValidator.prototype.getPasswordStrength = function (password) {
198
+ if (password === '') {
199
+ return false
200
+ }
201
+ return owaspPasswordStrengthTest.test(password)
202
+ }
203
+
204
+ /**
205
+ * Get the password strength level based on password strength feedback object given by OWASP
206
+ * @param passwordStrength
207
+ * @returns {number}
208
+ */
209
+ PasswordValidator.prototype.getStrengthLevel = function (passwordStrength) {
210
+ if (passwordStrength === false) {
211
+ return 0
212
+ }
213
+ if (passwordStrength.requiredTestErrors.length !== 0) {
214
+ return 1
215
+ }
216
+
217
+ if (passwordStrength.strong === false) {
218
+ return 2
219
+ }
220
+
221
+ if (passwordStrength.isPassphrase === false || passwordStrength.optionalTestErrors.length !== 0) {
222
+ return 3
223
+ }
224
+
225
+ return 4
226
+ }
227
+
228
+ PasswordValidator.prototype.LEVEL_TO_FEEDBACK_MAP = [
229
+ FEEDBACK_ERROR,
230
+ FEEDBACK_ERROR,
231
+ FEEDBACK_WARNING,
232
+ FEEDBACK_SUCCESS,
233
+ FEEDBACK_SUCCESS
234
+ ]
235
+
236
+ /**
237
+ * @returns {string}
238
+ */
239
+ PasswordValidator.prototype.getFeedbackFromLevel = function () {
240
+ return this.LEVEL_TO_FEEDBACK_MAP[this.currentStrengthLevel]
241
+ }
242
+
243
+ PasswordValidator.prototype.LEVEL_TO_PROGRESS_MAP = [
244
+ STRENGTH_PROGRESS_0,
245
+ STRENGTH_PROGRESS_1,
246
+ STRENGTH_PROGRESS_2,
247
+ STRENGTH_PROGRESS_3,
248
+ STRENGTH_PROGRESS_4
249
+ ]
250
+
251
+ /**
252
+ * Get the CSS class for the meter based on the current level
253
+ */
254
+ PasswordValidator.prototype.getStrengthLevelProgressClass = function () {
255
+ return this.LEVEL_TO_PROGRESS_MAP[this.currentStrengthLevel]
256
+ }
257
+
258
+ PasswordValidator.prototype.addPasswordError = function (error) {
259
+ this.errors.push(...(Array.isArray(error) ? error : [error]))
260
+ }
261
+
262
+ PasswordValidator.prototype.displayPasswordErrors = function () {
263
+ // Erase the error list content
264
+ while (this.passwordHelpText.firstChild) {
265
+ this.passwordHelpText.removeChild(this.passwordHelpText.firstChild)
266
+ }
267
+
268
+ // Add the errors in the stack to the DOM
269
+ this.errors.map((error) => {
270
+ const text = document.createTextNode(error)
271
+ const paragraph = document.createElement('p')
272
+ paragraph.appendChild(text)
273
+ this.passwordHelpText.appendChild(paragraph)
274
+ })
275
+ }
276
+
277
+ PasswordValidator.prototype.FEEDBACK_TO_ICON_MAP = []
278
+ PasswordValidator.prototype.FEEDBACK_TO_ICON_MAP[FEEDBACK_SUCCESS] = ICON_SUCCESS
279
+ PasswordValidator.prototype.FEEDBACK_TO_ICON_MAP[FEEDBACK_WARNING] = ICON_WARNING
280
+ PasswordValidator.prototype.FEEDBACK_TO_ICON_MAP[FEEDBACK_ERROR] = ICON_ERROR
281
+
282
+ /**
283
+ * @param success|error|warning feedback
284
+ */
285
+ PasswordValidator.prototype.getFeedbackIconClass = function (feedback) {
286
+ return this.FEEDBACK_TO_ICON_MAP[feedback]
287
+ }
288
+
289
+ PasswordValidator.prototype.FEEDBACK_TO_VALIDATION_MAP = []
290
+ PasswordValidator.prototype.FEEDBACK_TO_VALIDATION_MAP[FEEDBACK_SUCCESS] = VALIDATION_SUCCESS
291
+ PasswordValidator.prototype.FEEDBACK_TO_VALIDATION_MAP[FEEDBACK_WARNING] = VALIDATION_WARNING
292
+ PasswordValidator.prototype.FEEDBACK_TO_VALIDATION_MAP[FEEDBACK_ERROR] = VALIDATION_ERROR
293
+
294
+ /**
295
+ * @param success|error|warning feedback
296
+ */
297
+ PasswordValidator.prototype.getValidationClass = function (feedback) {
298
+ return this.FEEDBACK_TO_VALIDATION_MAP[feedback]
299
+ }
300
+
301
+ /**
302
+ * Validators
303
+ */
304
+
305
+ /**
306
+ * Check if both password fields are equal
307
+ * @returns {boolean}
308
+ */
309
+ PasswordValidator.prototype.checkPasswordFieldsEquality = function () {
310
+ return this.passwordField.value === this.repeatedPasswordField.value
311
+ }
312
+
313
+ /**
314
+ * Check if the password is leaked
315
+ * @param password
316
+ */
317
+ PasswordValidator.prototype.checkLeakedPassword = function (password) {
318
+ const url = 'https://api.pwnedpasswords.com/range/'
319
+
320
+ return new Promise(function (resolve, reject) {
321
+ this.sha1(password).then((digest) => {
322
+ const preFix = digest.slice(0, 5)
323
+ let suffix = digest.slice(5, digest.length)
324
+ suffix = suffix.toUpperCase()
325
+
326
+ return fetch(url + preFix)
327
+ .then(function (response) {
328
+ return response.text()
329
+ })
330
+ .then(function (data) {
331
+ resolve(data.indexOf(suffix) > -1)
332
+ })
333
+ .catch(function (err) {
334
+ reject(err)
335
+ })
336
+ })
337
+ }.bind(this))
338
+ }
339
+
340
+ PasswordValidator.prototype.handleLeakedPasswordResponse = function (hasPasswordLeaked) {
341
+ if (hasPasswordLeaked === true) {
342
+ this.currentStrengthLevel--
343
+ this.addPasswordError('This password was exposed in a data breach. Please use a more secure alternative one!')
344
+ }
345
+
346
+ this.setPasswordFeedback()
347
+ }
348
+
349
+ /**
350
+ * CSS Classes reseters
351
+ */
352
+
353
+ PasswordValidator.prototype.resetValidation = function (el) {
354
+ const tokenizedClasses = this.tokenize(
355
+ VALIDATION_ERROR,
356
+ VALIDATION_WARNING,
357
+ VALIDATION_SUCCESS
358
+ )
359
+
360
+ el.classList.remove.apply(
361
+ el.classList,
362
+ tokenizedClasses
363
+ )
364
+ }
365
+
366
+ PasswordValidator.prototype.resetFeedbackIcon = function (el) {
367
+ const tokenizedClasses = this.tokenize(
368
+ ICON_ERROR,
369
+ ICON_WARNING,
370
+ ICON_SUCCESS
371
+ )
372
+
373
+ el.classList.remove.apply(
374
+ el.classList,
375
+ tokenizedClasses
376
+ )
377
+ }
378
+
379
+ PasswordValidator.prototype.resetStrengthMeter = function () {
380
+ const tokenizedClasses = this.tokenize(
381
+ STRENGTH_PROGRESS_1,
382
+ STRENGTH_PROGRESS_2,
383
+ STRENGTH_PROGRESS_3,
384
+ STRENGTH_PROGRESS_4
385
+ )
386
+
387
+ this.passwordStrengthMeter.classList.remove.apply(
388
+ this.passwordStrengthMeter.classList,
389
+ tokenizedClasses
390
+ )
391
+ }
392
+
393
+ /**
394
+ * Helpers
395
+ */
396
+
397
+ PasswordValidator.prototype.getFormGroupElementForField = function (field) {
398
+ if (field === this.passwordField) {
399
+ return this.passwordGroup
400
+ }
401
+
402
+ if (field === this.repeatedPasswordField) {
403
+ return this.repeatedPasswordGroup
404
+ }
405
+ }
406
+
407
+ PasswordValidator.prototype.getFeedbackElementForField = function (field) {
408
+ if (field === this.passwordField) {
409
+ return this.passwordFeedback
410
+ }
411
+
412
+ if (field === this.repeatedPasswordField) {
413
+ return this.repeatedPasswordFeedback
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Returns an array of strings ready to be applied on classList.add or classList.remove
419
+ * @returns {string[]}
420
+ */
421
+ PasswordValidator.prototype.tokenize = function () {
422
+ const tokenArray = []
423
+ for (const i in arguments) {
424
+ tokenArray.push(arguments[i])
425
+ }
426
+ return tokenArray.join(' ').split(' ')
427
+ }
428
+
429
+ PasswordValidator.prototype.sha1 = function (str) {
430
+ const buffer = new TextEncoder('utf-8').encode(str)
431
+
432
+ return crypto.subtle.digest('SHA-1', buffer).then((hash) => {
433
+ return this.hex(hash)
434
+ })
435
+ }
436
+
437
+ PasswordValidator.prototype.hex = function (buffer) {
438
+ const hexCodes = []
439
+ const view = new DataView(buffer)
440
+ for (let i = 0; i < view.byteLength; i += 4) {
441
+ const value = view.getUint32(i)
442
+ const stringValue = value.toString(16)
443
+ const padding = '00000000'
444
+ const paddedValue = (padding + stringValue).slice(-padding.length)
445
+ hexCodes.push(paddedValue)
446
+ }
447
+ return hexCodes.join('')
448
+ }
449
+
450
+ new PasswordValidator(
451
+ document.getElementById('password'),
452
+ document.getElementById('repeat_password')
453
+ )
454
+ })()
@@ -0,0 +1,2 @@
1
+ # Report security issues responsibly
2
+ Contact: admin+security@inrupt.com
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ auth: 'oidc',
5
+ localAuth: {
6
+ tls: true,
7
+ password: true
8
+ },
9
+ configPath: './config',
10
+ dbPath: './.db',
11
+ port: 8443,
12
+ serverUri: 'https://localhost:8443',
13
+ webid: true,
14
+ strictOrigin: true,
15
+ trustedOrigins: [],
16
+ dataBrowserPath: 'default'
17
+
18
+ // For use in Enterprises to configure a HTTP proxy for all outbound HTTP requests from the SOLID server (we use
19
+ // https://www.npmjs.com/package/global-tunnel-ng).
20
+ // "httpProxy": {
21
+ // "tunnel": "neither",
22
+ // "host": "proxy.example.com",
23
+ // "port": 12345
24
+ // }
25
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "useTheBigUsernameBlacklist": true,
3
+ "customBlacklistedUsernames": []
4
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "root": "./data",
3
+ "port": "8443",
4
+ "serverUri": "https://localhost:8443",
5
+ "webid": true,
6
+ "mount": "/",
7
+ "configPath": "./config",
8
+ "dbPath": "./.db",
9
+ "sslKey": "./privkey.pem",
10
+ "sslCert": "./fullchain.pem",
11
+ "multiuser": true,
12
+ "corsProxy": "/proxy",
13
+ "server": {
14
+ "name": "",
15
+ "description": "",
16
+ "logo": ""
17
+ },
18
+ "enforceToc": true,
19
+ "disablePasswordChecks": false,
20
+ "tocUri": "https://your-toc",
21
+ "supportEmail": "Your support email address"
22
+ }
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Returns a partial Email object (minus the `to` and `from` properties),
5
+ * suitable for sending with Nodemailer.
6
+ *
7
+ * Used to send a Delete Account email, upon user request
8
+ *
9
+ * @param data {Object}
10
+ *
11
+ * @param data.deleteUrl {string}
12
+ * @param data.webId {string}
13
+ *
14
+ * @return {Object}
15
+ */
16
+ function render (data) {
17
+ return {
18
+ subject: 'Delete Solid-account request',
19
+
20
+ /**
21
+ * Text version
22
+ */
23
+ text: `Hi,
24
+
25
+ We received a request to delete your Solid account, ${data.webId}
26
+
27
+ To delete your account, click on the following link:
28
+
29
+ ${data.deleteUrl}
30
+
31
+ If you did not mean to delete your account, ignore this email.`,
32
+
33
+ /**
34
+ * HTML version
35
+ */
36
+ html: `<p>Hi,</p>
37
+
38
+ <p>We received a request to delete your Solid account, ${data.webId}</p>
39
+
40
+ <p>To delete your account, click on the following link:</p>
41
+
42
+ <p><a href="${data.deleteUrl}">${data.deleteUrl}</a></p>
43
+
44
+ <p>If you did not mean to delete your account, ignore this email.</p>
45
+ `
46
+ }
47
+ }
48
+
49
+ module.exports.render = render
@@ -0,0 +1,30 @@
1
+ module.exports.render = render
2
+
3
+ function render (data) {
4
+ return {
5
+ subject: `Invalid username for account ${data.accountUri}`,
6
+
7
+ /**
8
+ * Text version
9
+ */
10
+ text: `Hi,
11
+
12
+ We're sorry to inform you that the username for account ${data.accountUri} is not allowed after changes to username policy.
13
+
14
+ This account has been set to be deleted at ${data.dateOfRemoval}.
15
+
16
+ ${data.supportEmail ? `Please contact ${data.supportEmail} if you want to move your account.` : ''}`,
17
+
18
+ /**
19
+ * HTML version
20
+ */
21
+ html: `<p>Hi,</p>
22
+
23
+ <p>We're sorry to inform you that the username for account ${data.accountUri} is not allowed after changes to username policy.</p>
24
+
25
+ <p>This account has been set to be deleted at ${data.dateOfRemoval}.</p>
26
+
27
+ ${data.supportEmail ? `<p>Please contact ${data.supportEmail} if you want to move your account.</p>` : ''}
28
+ `
29
+ }
30
+ }
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Returns a partial Email object (minus the `to` and `from` properties),
5
+ * suitable for sending with Nodemailer.
6
+ *
7
+ * Used to send a Reset Password email, upon user request
8
+ *
9
+ * @param data {Object}
10
+ *
11
+ * @param data.resetUrl {string}
12
+ * @param data.webId {string}
13
+ *
14
+ * @return {Object}
15
+ */
16
+ function render (data) {
17
+ return {
18
+ subject: 'Account password reset',
19
+
20
+ /**
21
+ * Text version
22
+ */
23
+ text: `Hi,
24
+
25
+ We received a request to reset your password for your Solid account, ${data.webId}
26
+
27
+ To reset your password, click on the following link:
28
+
29
+ ${data.resetUrl}
30
+
31
+ If you did not mean to reset your password, ignore this email, your password will not change.`,
32
+
33
+ /**
34
+ * HTML version
35
+ */
36
+ html: `<p>Hi,</p>
37
+
38
+ <p>We received a request to reset your password for your Solid account, ${data.webId}</p>
39
+
40
+ <p>To reset your password, click on the following link:</p>
41
+
42
+ <p><a href="${data.resetUrl}">${data.resetUrl}</a></p>
43
+
44
+ <p>If you did not mean to reset your password, ignore this email, your password will not change.</p>
45
+ `
46
+ }
47
+ }
48
+
49
+ module.exports.render = render
@@ -0,0 +1,39 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Returns a partial Email object (minus the `to` and `from` properties),
5
+ * suitable for sending with Nodemailer.
6
+ *
7
+ * Used to send a Welcome email after a new user account has been created.
8
+ *
9
+ * @param data {Object}
10
+ *
11
+ * @param data.webid {string}
12
+ *
13
+ * @return {Object}
14
+ */
15
+ function render (data) {
16
+ return {
17
+ subject: 'Welcome to Solid',
18
+
19
+ /**
20
+ * Text version of the Welcome email
21
+ */
22
+ text: `Welcome to Solid!
23
+
24
+ Your account has been created.
25
+
26
+ Your Web Id: ${data.webid}`,
27
+
28
+ /**
29
+ * HTML version of the Welcome email
30
+ */
31
+ html: `<p>Welcome to Solid!</p>
32
+
33
+ <p>Your account has been created.</p>
34
+
35
+ <p>Your Web Id: ${data.webid}</p>`
36
+ }
37
+ }
38
+
39
+ module.exports.render = render
@@ -0,0 +1,26 @@
1
+ # Root ACL resource for the user account
2
+ @prefix acl: <http://www.w3.org/ns/auth/acl#>.
3
+ @prefix foaf: <http://xmlns.com/foaf/0.1/>.
4
+
5
+ # The homepage is readable by the public
6
+ <#public>
7
+ a acl:Authorization;
8
+ acl:agentClass foaf:Agent;
9
+ acl:accessTo </>;
10
+ acl:mode acl:Read.
11
+
12
+ # The owner has full access to every resource in their pod.
13
+ # Other agents have no access rights,
14
+ # unless specifically authorized in other .acl resources.
15
+ <#owner>
16
+ a acl:Authorization;
17
+ acl:agent <{{webId}}>;
18
+ # Optional owner email, to be used for account recovery:
19
+ {{#if email}}acl:agent <mailto:{{{email}}}>;{{/if}}
20
+ # Set the access to the root storage folder itself
21
+ acl:accessTo </>;
22
+ # All resources will inherit this authorization, by default
23
+ acl:default </>;
24
+ # The owner has all of the access modes allowed
25
+ acl:mode
26
+ acl:Read, acl:Write, acl:Control.