@things-factory/auth-ui 10.1.13 → 10.1.17

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 (83) hide show
  1. package/dist-client/components/role-template-picker.js +6 -8
  2. package/dist-client/components/role-template-picker.js.map +1 -1
  3. package/dist-client/components/secret-field.d.ts +35 -0
  4. package/dist-client/components/secret-field.js +149 -0
  5. package/dist-client/components/secret-field.js.map +1 -0
  6. package/dist-client/pages/app-binding/app-binding-list-query.test.d.ts +1 -0
  7. package/dist-client/pages/app-binding/app-binding-list-query.test.js +46 -0
  8. package/dist-client/pages/app-binding/app-binding-list-query.test.js.map +1 -0
  9. package/dist-client/pages/app-binding/app-binding.d.ts +1 -0
  10. package/dist-client/pages/app-binding/app-binding.js +8 -8
  11. package/dist-client/pages/app-binding/app-binding.js.map +1 -1
  12. package/dist-client/pages/app-binding/app-bindings.d.ts +63 -2
  13. package/dist-client/pages/app-binding/app-bindings.js +199 -117
  14. package/dist-client/pages/app-binding/app-bindings.js.map +1 -1
  15. package/dist-client/pages/appliance/appliance-list-query.test.d.ts +1 -0
  16. package/dist-client/pages/appliance/appliance-list-query.test.js +58 -0
  17. package/dist-client/pages/appliance/appliance-list-query.test.js.map +1 -0
  18. package/dist-client/pages/appliance/appliance.d.ts +1 -0
  19. package/dist-client/pages/appliance/appliance.js +2 -4
  20. package/dist-client/pages/appliance/appliance.js.map +1 -1
  21. package/dist-client/pages/appliance/home.d.ts +61 -2
  22. package/dist-client/pages/appliance/home.js +200 -122
  23. package/dist-client/pages/appliance/home.js.map +1 -1
  24. package/dist-client/pages/application/application.d.ts +1 -0
  25. package/dist-client/pages/application/application.js +10 -3
  26. package/dist-client/pages/application/application.js.map +1 -1
  27. package/dist-client/pages/application/applications.d.ts +61 -2
  28. package/dist-client/pages/application/applications.js +193 -128
  29. package/dist-client/pages/application/applications.js.map +1 -1
  30. package/dist-client/pages/application/register.js +81 -27
  31. package/dist-client/pages/application/register.js.map +1 -1
  32. package/dist-client/pages/auth-provider/auth-provider-management.d.ts +4 -2
  33. package/dist-client/pages/auth-provider/auth-provider-management.js +35 -6
  34. package/dist-client/pages/auth-provider/auth-provider-management.js.map +1 -1
  35. package/dist-client/pages/domain-owner/domain-owner-management.d.ts +2 -0
  36. package/dist-client/pages/domain-owner/domain-owner-management.js +34 -7
  37. package/dist-client/pages/domain-owner/domain-owner-management.js.map +1 -1
  38. package/dist-client/pages/role/role-list-page.d.ts +20 -0
  39. package/dist-client/pages/role/role-list-page.js +58 -1
  40. package/dist-client/pages/role/role-list-page.js.map +1 -1
  41. package/dist-client/pages/role/role-privilege-page.js +1 -10
  42. package/dist-client/pages/role/role-privilege-page.js.map +1 -1
  43. package/dist-client/pages/secrets-are-not-printed.test.d.ts +1 -0
  44. package/dist-client/pages/secrets-are-not-printed.test.js +70 -0
  45. package/dist-client/pages/secrets-are-not-printed.test.js.map +1 -0
  46. package/dist-client/tsconfig.tsbuildinfo +1 -1
  47. package/dist-client/utils/application-status.d.ts +32 -0
  48. package/dist-client/utils/application-status.js +45 -0
  49. package/dist-client/utils/application-status.js.map +1 -0
  50. package/dist-client/utils/application-status.test.d.ts +1 -0
  51. package/dist-client/utils/application-status.test.js +45 -0
  52. package/dist-client/utils/application-status.test.js.map +1 -0
  53. package/dist-client/utils/form-values.d.ts +42 -0
  54. package/dist-client/utils/form-values.js +57 -0
  55. package/dist-client/utils/form-values.js.map +1 -0
  56. package/dist-client/utils/form-values.test.d.ts +1 -0
  57. package/dist-client/utils/form-values.test.js +62 -0
  58. package/dist-client/utils/form-values.test.js.map +1 -0
  59. package/dist-client/utils/list-result.d.ts +62 -0
  60. package/dist-client/utils/list-result.js +92 -0
  61. package/dist-client/utils/list-result.js.map +1 -0
  62. package/dist-client/utils/list-result.test.d.ts +1 -0
  63. package/dist-client/utils/list-result.test.js +160 -0
  64. package/dist-client/utils/list-result.test.js.map +1 -0
  65. package/dist-client/utils/privilege-axis.d.ts +52 -0
  66. package/dist-client/utils/privilege-axis.js +55 -0
  67. package/dist-client/utils/privilege-axis.js.map +1 -0
  68. package/dist-client/utils/privilege-axis.test.d.ts +1 -0
  69. package/dist-client/utils/privilege-axis.test.js +39 -0
  70. package/dist-client/utils/privilege-axis.test.js.map +1 -0
  71. package/dist-client/utils/secret-display.d.ts +51 -0
  72. package/dist-client/utils/secret-display.js +61 -0
  73. package/dist-client/utils/secret-display.js.map +1 -0
  74. package/dist-client/utils/secret-display.test.d.ts +1 -0
  75. package/dist-client/utils/secret-display.test.js +59 -0
  76. package/dist-client/utils/secret-display.test.js.map +1 -0
  77. package/dist-server/tsconfig.tsbuildinfo +1 -1
  78. package/package.json +4 -4
  79. package/translations/en.json +33 -0
  80. package/translations/ja.json +33 -0
  81. package/translations/ko.json +33 -0
  82. package/translations/ms.json +33 -0
  83. package/translations/zh.json +33 -0
@@ -0,0 +1,70 @@
1
+ import { readdirSync, readFileSync, statSync } from 'fs';
2
+ import { join } from 'path';
3
+ /**
4
+ * No auth screen prints a credential into a plain input.
5
+ *
6
+ * Three of them did, from the moment the page loaded: the binding detail showed an access
7
+ * token and a refresh token, the appliance detail showed an access token, the application
8
+ * detail showed its client secret. `secret-field` replaced all four — masked, copyable
9
+ * without revealing, revealed only when the reader asks.
10
+ *
11
+ * This is worth a test rather than a habit because the wrong version is the natural one to
12
+ * write. A readonly input beside a copy button is what a credential looks like in every
13
+ * other admin console anyone has seen, it reviews cleanly, and nothing in the build objects.
14
+ *
15
+ * ⚠ Comments are stripped first — the prose here and in those screens names every field this
16
+ * searches for, explaining why they are absent.
17
+ */
18
+ const SECRETS = ['appSecret', 'refreshToken', 'clientSecret', 'privateKey', 'accessToken'];
19
+ const PAGES = join(__dirname);
20
+ function tsFilesUnder(dir) {
21
+ return readdirSync(dir).flatMap(entry => {
22
+ const path = join(dir, entry);
23
+ if (statSync(path).isDirectory()) {
24
+ return tsFilesUnder(path);
25
+ }
26
+ return entry.endsWith('.ts') && !entry.endsWith('.test.ts') ? [path] : [];
27
+ });
28
+ }
29
+ function sourceOf(path) {
30
+ return readFileSync(path, 'utf-8')
31
+ .replace(/\/\*[\s\S]*?\*\//g, '')
32
+ .replace(/^[ \t]*\/\/.*$/gm, '')
33
+ .replace(/<!--[\s\S]*?-->/g, '');
34
+ }
35
+ describe('auth screens', () => {
36
+ it('never bind a credential into a plain input', () => {
37
+ const offenders = [];
38
+ for (const path of tsFilesUnder(PAGES)) {
39
+ const source = sourceOf(path);
40
+ for (const secret of SECRETS) {
41
+ /*
42
+ * An `<input>` whose value expression ends at the secret's name. The trailing
43
+ * boundary matters: `accessTokenUrl` is an endpoint, not a credential, and an
44
+ * earlier version of this search flagged it.
45
+ */
46
+ const bound = new RegExp(`<input[^>]*\\.value=\\$\\{[^}]*\\b${secret}\\b(?!Url)[^}]*\\}`);
47
+ if (bound.test(source)) {
48
+ offenders.push(`${path.split('/pages/')[1]} — ${secret}`);
49
+ }
50
+ }
51
+ }
52
+ expect(offenders).toEqual([]);
53
+ });
54
+ it('still knows what it is looking for', () => {
55
+ /*
56
+ * A search that matches nothing passes whether the screens are clean or the pattern is
57
+ * broken. This proves the pattern finds the shape it is meant to find, so a green run
58
+ * above means the screens are clean rather than the regex is dead.
59
+ */
60
+ const sample = '<input id="x" type="text" .value=${app.appSecret} readonly />';
61
+ const bound = new RegExp(`<input[^>]*\\.value=\\$\\{[^}]*\\bappSecret\\b(?!Url)[^}]*\\}`);
62
+ expect(bound.test(sample)).toBe(true);
63
+ });
64
+ it('does not mistake an endpoint for a credential', () => {
65
+ const sample = '<input id="x" type="text" .value=${app.accessTokenUrl} readonly />';
66
+ const bound = new RegExp(`<input[^>]*\\.value=\\$\\{[^}]*\\baccessToken\\b(?!Url)[^}]*\\}`);
67
+ expect(bound.test(sample)).toBe(false);
68
+ });
69
+ });
70
+ //# sourceMappingURL=secrets-are-not-printed.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets-are-not-printed.test.js","sourceRoot":"","sources":["../../client/pages/secrets-are-not-printed.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B;;;;;;;;;;;;;;GAcG;AAEH,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,CAAC,CAAA;AAE1F,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;AAE7B,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAE7B,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACjC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC;QAED,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3E,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;SAC/B,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;SAChC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAA;AACpC,CAAC;AAED,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,SAAS,GAAa,EAAE,CAAA;QAE9B,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YAE7B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B;;;;mBAIG;gBACH,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,qCAAqC,MAAM,oBAAoB,CAAC,CAAA;gBAEzF,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACvB,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAA;gBAC3D,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C;;;;WAIG;QACH,MAAM,MAAM,GAAG,+DAA+D,CAAA;QAC9E,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,+DAA+D,CAAC,CAAA;QAEzF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,MAAM,GAAG,oEAAoE,CAAA;QACnF,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,iEAAiE,CAAC,CAAA;QAE3F,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import { readdirSync, readFileSync, statSync } from 'fs'\nimport { join } from 'path'\n\n/**\n * No auth screen prints a credential into a plain input.\n *\n * Three of them did, from the moment the page loaded: the binding detail showed an access\n * token and a refresh token, the appliance detail showed an access token, the application\n * detail showed its client secret. `secret-field` replaced all four — masked, copyable\n * without revealing, revealed only when the reader asks.\n *\n * This is worth a test rather than a habit because the wrong version is the natural one to\n * write. A readonly input beside a copy button is what a credential looks like in every\n * other admin console anyone has seen, it reviews cleanly, and nothing in the build objects.\n *\n * ⚠ Comments are stripped first — the prose here and in those screens names every field this\n * searches for, explaining why they are absent.\n */\n\nconst SECRETS = ['appSecret', 'refreshToken', 'clientSecret', 'privateKey', 'accessToken']\n\nconst PAGES = join(__dirname)\n\nfunction tsFilesUnder(dir: string): string[] {\n return readdirSync(dir).flatMap(entry => {\n const path = join(dir, entry)\n\n if (statSync(path).isDirectory()) {\n return tsFilesUnder(path)\n }\n\n return entry.endsWith('.ts') && !entry.endsWith('.test.ts') ? [path] : []\n })\n}\n\nfunction sourceOf(path: string): string {\n return readFileSync(path, 'utf-8')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/^[ \\t]*\\/\\/.*$/gm, '')\n .replace(/<!--[\\s\\S]*?-->/g, '')\n}\n\ndescribe('auth screens', () => {\n it('never bind a credential into a plain input', () => {\n const offenders: string[] = []\n\n for (const path of tsFilesUnder(PAGES)) {\n const source = sourceOf(path)\n\n for (const secret of SECRETS) {\n /*\n * An `<input>` whose value expression ends at the secret's name. The trailing\n * boundary matters: `accessTokenUrl` is an endpoint, not a credential, and an\n * earlier version of this search flagged it.\n */\n const bound = new RegExp(`<input[^>]*\\\\.value=\\\\$\\\\{[^}]*\\\\b${secret}\\\\b(?!Url)[^}]*\\\\}`)\n\n if (bound.test(source)) {\n offenders.push(`${path.split('/pages/')[1]} — ${secret}`)\n }\n }\n }\n\n expect(offenders).toEqual([])\n })\n\n it('still knows what it is looking for', () => {\n /*\n * A search that matches nothing passes whether the screens are clean or the pattern is\n * broken. This proves the pattern finds the shape it is meant to find, so a green run\n * above means the screens are clean rather than the regex is dead.\n */\n const sample = '<input id=\"x\" type=\"text\" .value=${app.appSecret} readonly />'\n const bound = new RegExp(`<input[^>]*\\\\.value=\\\\$\\\\{[^}]*\\\\bappSecret\\\\b(?!Url)[^}]*\\\\}`)\n\n expect(bound.test(sample)).toBe(true)\n })\n\n it('does not mistake an endpoint for a credential', () => {\n const sample = '<input id=\"x\" type=\"text\" .value=${app.accessTokenUrl} readonly />'\n const bound = new RegExp(`<input[^>]*\\\\.value=\\\\$\\\\{[^}]*\\\\baccessToken\\\\b(?!Url)[^}]*\\\\}`)\n\n expect(bound.test(sample)).toBe(false)\n })\n})\n"]}