@cratis/arc 22.45.0 → 22.46.0

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 (130) hide show
  1. package/dist/cjs/identity/IdentityProvider.d.ts +11 -2
  2. package/dist/cjs/identity/IdentityProvider.d.ts.map +1 -1
  3. package/dist/cjs/identity/IdentityProvider.js +118 -44
  4. package/dist/cjs/identity/IdentityProvider.js.map +1 -1
  5. package/dist/cjs/identity/deserializeIdentityDetails.d.ts.map +1 -1
  6. package/dist/cjs/identity/deserializeIdentityDetails.js +1 -2
  7. package/dist/cjs/identity/deserializeIdentityDetails.js.map +1 -1
  8. package/dist/esm/identity/IdentityProvider.d.ts +11 -2
  9. package/dist/esm/identity/IdentityProvider.d.ts.map +1 -1
  10. package/dist/esm/identity/IdentityProvider.js +118 -44
  11. package/dist/esm/identity/IdentityProvider.js.map +1 -1
  12. package/dist/esm/identity/deserializeIdentityDetails.d.ts.map +1 -1
  13. package/dist/esm/identity/deserializeIdentityDetails.js +1 -2
  14. package/dist/esm/identity/deserializeIdentityDetails.js.map +1 -1
  15. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.d.ts +11 -0
  16. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.d.ts.map +1 -0
  17. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.js +42 -0
  18. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.js.map +1 -0
  19. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.d.ts +7 -0
  20. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.d.ts.map +1 -0
  21. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.js +19 -0
  22. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.js.map +1 -0
  23. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.d.ts +5 -0
  24. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.d.ts.map +1 -0
  25. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.js +5 -0
  26. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.js.map +1 -0
  27. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.d.ts +1 -0
  28. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.d.ts.map +1 -1
  29. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.js +11 -0
  30. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.js.map +1 -1
  31. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.d.ts +2 -0
  32. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.d.ts.map +1 -0
  33. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.js +15 -0
  34. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.js.map +1 -0
  35. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.d.ts +2 -0
  36. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.d.ts.map +1 -0
  37. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.js +17 -0
  38. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.js.map +1 -0
  39. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.d.ts +2 -0
  40. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.d.ts.map +1 -0
  41. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.js +18 -0
  42. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.js.map +1 -0
  43. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.d.ts +2 -0
  44. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.d.ts.map +1 -0
  45. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.js +20 -0
  46. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.js.map +1 -0
  47. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.d.ts +2 -0
  48. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.d.ts.map +1 -0
  49. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.js +24 -0
  50. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.js.map +1 -0
  51. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.d.ts +2 -0
  52. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.d.ts.map +1 -0
  53. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.js +16 -0
  54. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.js.map +1 -0
  55. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.d.ts +2 -0
  56. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.d.ts.map +1 -0
  57. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.js +15 -0
  58. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.js.map +1 -0
  59. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.js +2 -3
  60. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.js.map +1 -1
  61. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.d.ts +2 -0
  62. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.d.ts.map +1 -0
  63. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.js +18 -0
  64. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.js.map +1 -0
  65. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_roles.js +2 -3
  66. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_roles.js.map +1 -1
  67. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_type_safe_details.js +2 -3
  68. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_type_safe_details.js.map +1 -1
  69. package/dist/esm/identity/for_IdentityProvider/when_getting_current/without_roles.js +2 -3
  70. package/dist/esm/identity/for_IdentityProvider/when_getting_current/without_roles.js.map +1 -1
  71. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.d.ts +2 -0
  72. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.d.ts.map +1 -0
  73. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.js +18 -0
  74. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.js.map +1 -0
  75. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.d.ts +2 -0
  76. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.d.ts.map +1 -0
  77. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.js +17 -0
  78. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.js.map +1 -0
  79. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.d.ts +2 -0
  80. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.d.ts.map +1 -0
  81. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.js +13 -0
  82. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.js.map +1 -0
  83. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.d.ts +2 -0
  84. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.d.ts.map +1 -0
  85. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.js +17 -0
  86. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.js.map +1 -0
  87. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.d.ts +2 -0
  88. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.d.ts.map +1 -0
  89. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.js +21 -0
  90. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.js.map +1 -0
  91. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.d.ts +2 -0
  92. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.d.ts.map +1 -0
  93. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.js +16 -0
  94. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.js.map +1 -0
  95. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.d.ts +2 -0
  96. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.d.ts.map +1 -0
  97. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.js +17 -0
  98. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.js.map +1 -0
  99. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.d.ts +2 -0
  100. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.d.ts.map +1 -0
  101. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.js +15 -0
  102. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.js.map +1 -0
  103. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  104. package/identity/IdentityProvider.ts +137 -43
  105. package/identity/deserializeIdentityDetails.ts +1 -2
  106. package/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.ts +46 -0
  107. package/identity/for_IdentityProvider/given/a_cookie_first_backend.ts +25 -0
  108. package/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.ts +8 -0
  109. package/identity/for_IdentityProvider/given/an_identity_provider.ts +19 -0
  110. package/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.ts +21 -0
  111. package/identity/for_IdentityProvider/when_clearing_cache.ts +24 -0
  112. package/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.ts +24 -0
  113. package/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.ts +31 -0
  114. package/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.ts +38 -0
  115. package/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.ts +23 -0
  116. package/identity/for_IdentityProvider/when_getting_current/twice.ts +22 -0
  117. package/identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.ts +2 -3
  118. package/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.ts +29 -0
  119. package/identity/for_IdentityProvider/when_getting_current/with_roles.ts +2 -3
  120. package/identity/for_IdentityProvider/when_getting_current/with_type_safe_details.ts +2 -4
  121. package/identity/for_IdentityProvider/when_getting_current/without_roles.ts +2 -3
  122. package/identity/for_IdentityProvider/when_refreshing/after_getting_current.ts +25 -0
  123. package/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.ts +23 -0
  124. package/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.ts +19 -0
  125. package/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.ts +24 -0
  126. package/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.ts +27 -0
  127. package/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.ts +22 -0
  128. package/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.ts +23 -0
  129. package/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.ts +21 -0
  130. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider.js';\nimport { IIdentity } from './IIdentity.js';\nimport { IdentityProviderResult } from './IdentityProviderResult.js';\nimport { deserializeIdentityDetails } from './deserializeIdentityDetails.js';\nimport { GetHttpHeaders } from '../GetHttpHeaders.js';\nimport { Globals } from '../Globals.js';\nimport { UrlHelpers } from '../UrlHelpers.js';\nimport { joinPaths } from '../joinPaths.js';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = deserializeIdentityDetails(type, result.details);\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.clearIdentityCookie();\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n if (!response.ok) {\n return IdentityProvider.notSet(type);\n }\n\n const result = await response.json() as IdentityProviderResult;\n const details = deserializeIdentityDetails(type, result.details);\n\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static notSet<TDetails extends object = object>(type?: Constructor<TDetails>): IIdentity<TDetails> {\n return {\n id: '',\n name: '',\n roles: [],\n details: {} as TDetails,\n isSet: false,\n isInRole: () => false,\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static getCookie() {\n if (typeof document === 'undefined') return [];\n const decoded = decodeURIComponent(document.cookie);\n const cookies = decoded.split(';').map(_ => _.trim());\n const cookie = cookies.find(_ => _.indexOf(`${IdentityProvider.CookieName}=`) == 0);\n if (cookie) {\n const keyValue = cookie.split('=');\n return [keyValue[0].trim(), keyValue[1].trim()];\n }\n return [];\n }\n\n /**\n * Clears the identity cookie used by Arc to cache the current identity.\n * Call this when the user logs out to ensure subsequent requests and WebSocket\n * connections do not carry stale credentials.\n */\n static clearIdentityCookie(): void {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n"],"names":["IdentityProvider","IIdentityProvider","CookieName","httpHeadersCallback","apiBasePath","origin","setHttpHeadersCallback","callback","setApiBasePath","setOrigin","getCurrent","type","cookie","getCookie","length","json","atob","result","JSON","parse","details","deserializeIdentityDetails","id","name","roles","isSet","isInRole","role","includes","refresh","identity","clearIdentityCookie","Globals","route","joinPaths","url","UrlHelpers","createUrlFrom","response","fetch","method","headers","ok","notSet","document","decoded","decodeURIComponent","cookies","split","map","_","trim","find","indexOf","keyValue"],"mappings":"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"}
1
+ {"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider.js';\nimport { IIdentity } from './IIdentity.js';\nimport { IdentityProviderResult } from './IdentityProviderResult.js';\nimport { deserializeIdentityDetails } from './deserializeIdentityDetails.js';\nimport { GetHttpHeaders } from '../GetHttpHeaders.js';\nimport { Globals } from '../Globals.js';\nimport { UrlHelpers } from '../UrlHelpers.js';\nimport { joinPaths } from '../joinPaths.js';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n *\n * The identity comes from the `/.cratis/me` endpoint, which derives it from the authenticated request. The\n * result is kept in memory for the page, so repeated calls to {@link IdentityProvider.getCurrent} do not each go to\n * the server; {@link IdentityProvider.refresh} always asks the server again.\n *\n * Only when the server has no `/.cratis/me` endpoint (it answers 404) does it fall back to the readable\n * `.cratis-identity` cookie earlier versions relied on, and it warns when it does. That fallback is for the transition\n * and will be removed.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n /**\n * The name of the identity cookie earlier versions of Arc wrote and read.\n * @deprecated The identity comes from the `/.cratis/me` endpoint. The cookie is only read when that endpoint does\n * not exist, and that fallback will be removed.\n */\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n private static cachedResult: Promise<IdentityProviderResult | undefined> | undefined;\n private static hasWarnedAboutLegacyCookie = false;\n private static legacyCookie: string | undefined;\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n if (IdentityProvider.apiBasePath !== apiBasePath) {\n IdentityProvider.cachedResult = undefined;\n IdentityProvider.legacyCookie = undefined;\n }\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n if (IdentityProvider.origin !== origin) {\n IdentityProvider.cachedResult = undefined;\n IdentityProvider.legacyCookie = undefined;\n }\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The identity is fetched from `/.cratis/me` the first time and kept in memory until\n * {@link IdentityProvider.refresh} or {@link IdentityProvider.clearCache} is called. An identity that could not be\n * resolved is not kept, so the next call asks the server again.\n * The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n if (!IdentityProvider.cachedResult) {\n IdentityProvider.fetchAndCache();\n }\n const result = await IdentityProvider.cachedResult;\n return IdentityProvider.toIdentity(result, type);\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n /**\n * Fetches the current identity from `/.cratis/me`, replacing what is kept in memory.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n */\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n // Earlier backends resolve the cookie before consulting the current credentials. Retain it during the\n // request for a possible 404 transition fallback, but do not send it with an explicit refresh request.\n IdentityProvider.legacyCookie = IdentityProvider.readLegacyCookie() ?? IdentityProvider.legacyCookie;\n IdentityProvider.cachedResult = undefined;\n IdentityProvider.expireLegacyCookie();\n const result = await IdentityProvider.fetchAndCache();\n return IdentityProvider.toIdentity(result, type);\n }\n\n /**\n * Forgets the identity kept in memory, so the next {@link IdentityProvider.getCurrent} asks the server again.\n * It also expires a readable `.cratis-identity` cookie left by an earlier version. Call this when the user logs out.\n */\n static clearCache(): void {\n IdentityProvider.cachedResult = undefined;\n IdentityProvider.legacyCookie = undefined;\n IdentityProvider.expireLegacyCookie();\n }\n\n /**\n * Forgets the identity kept in memory.\n * @deprecated Arc no longer keeps the identity in a cookie. Use {@link IdentityProvider.clearCache} instead.\n */\n static clearIdentityCookie(): void {\n IdentityProvider.clearCache();\n }\n\n private static expireLegacyCookie(): void {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;\n }\n\n private static readLegacyCookie(): string | undefined {\n if (typeof document === 'undefined') return undefined;\n const prefix = `${IdentityProvider.CookieName}=`;\n return document.cookie.split(';').map(_ => _.trim()).find(_ => _.startsWith(prefix));\n }\n\n private static fetchAndCache(): Promise<IdentityProviderResult | undefined> {\n const pending = IdentityProvider.fetchResult();\n IdentityProvider.cachedResult = pending;\n\n // Only a resolved identity is worth keeping: an unset one, or a failed request, has to be asked for\n // again - otherwise a page that loaded before sign-in would never see the user who signed in.\n const forget = () => {\n if (IdentityProvider.cachedResult === pending) {\n IdentityProvider.cachedResult = undefined;\n }\n };\n pending.then(result => {\n if (!result) forget();\n }, forget);\n\n return pending;\n }\n\n private static async fetchResult(): Promise<IdentityProviderResult | undefined> {\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n // No identity endpoint at all - an application that has not mapped one, or one whose identity comes from a\n // proxy in front of it. Anything else, a 401 or 403 above all, is the server's answer and a cookie the\n // browser holds must never overrule it.\n if (response.status === 404) {\n return IdentityProvider.fromLegacyCookie();\n }\n\n IdentityProvider.legacyCookie = undefined;\n if (!response.ok) {\n return undefined;\n }\n\n return await response.json() as IdentityProviderResult;\n }\n\n private static fromLegacyCookie(): IdentityProviderResult | undefined {\n if (typeof document === 'undefined') return undefined;\n // A proxy may issue a newer cookie on the response. Prefer it over the one expired before the request.\n const responseCookie = IdentityProvider.readLegacyCookie();\n const cookie = responseCookie ?? IdentityProvider.legacyCookie;\n if (!cookie) return undefined;\n IdentityProvider.legacyCookie = cookie;\n\n try {\n const result = JSON.parse(atob(decodeURIComponent(cookie.substring(`${IdentityProvider.CookieName}=`.length)))) as IdentityProviderResult;\n // The proxy may not reissue its cookie while its own authorization record remains valid. Restore the\n // transition fallback after a 404 so it also survives a reload, without changing a response cookie.\n if (!responseCookie) document.cookie = `${cookie};path=/;samesite=lax${location.protocol === 'https:' ? ';secure' : ''}`;\n if (!IdentityProvider.hasWarnedAboutLegacyCookie) {\n IdentityProvider.hasWarnedAboutLegacyCookie = true;\n console.warn(\n `The server has no '/.cratis/me' endpoint, so the identity was read from the '${IdentityProvider.CookieName}' cookie. ` +\n 'That cookie is not protected and the fallback will be removed in a future major version. ' +\n 'Expose /.cratis/me to the frontend: https://github.com/Cratis/Arc/blob/main/Documentation/backend/csharp/identity/migrating-from-the-identity-cookie.md');\n }\n return result;\n } catch {\n return undefined;\n }\n }\n\n private static toIdentity<TDetails extends object = object>(result: IdentityProviderResult | undefined, type?: Constructor<TDetails>): IIdentity<TDetails> {\n if (!result) {\n return IdentityProvider.notSet(type);\n }\n\n const details = deserializeIdentityDetails(type, result.details);\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static notSet<TDetails extends object = object>(type?: Constructor<TDetails>): IIdentity<TDetails> {\n return {\n id: '',\n name: '',\n roles: [],\n details: {} as TDetails,\n isSet: false,\n isInRole: () => false,\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n}\n"],"names":["IdentityProvider","IIdentityProvider","CookieName","httpHeadersCallback","apiBasePath","origin","cachedResult","hasWarnedAboutLegacyCookie","legacyCookie","setHttpHeadersCallback","callback","setApiBasePath","undefined","setOrigin","getCurrent","type","fetchAndCache","result","toIdentity","refresh","readLegacyCookie","expireLegacyCookie","clearCache","clearIdentityCookie","document","cookie","prefix","split","map","_","trim","find","startsWith","pending","fetchResult","forget","then","Globals","route","joinPaths","url","UrlHelpers","createUrlFrom","response","fetch","method","headers","status","fromLegacyCookie","ok","json","responseCookie","JSON","parse","atob","decodeURIComponent","substring","length","location","protocol","console","warn","notSet","details","deserializeIdentityDetails","id","name","roles","isSet","isInRole","role","includes"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"deserializeIdentityDetails.d.ts","sourceRoot":"","sources":["../../../identity/deserializeIdentityDetails.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAA0B,MAAM,sBAAsB,CAAC;AAmD3E,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAwBnG"}
1
+ {"version":3,"file":"deserializeIdentityDetails.d.ts","sourceRoot":"","sources":["../../../identity/deserializeIdentityDetails.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAA0B,MAAM,sBAAsB,CAAC;AAkD3E,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAwBnG"}
@@ -28,8 +28,7 @@ import { Fields, JsonSerializer } from '@cratis/fundamentals';
28
28
  * would otherwise crash or silently destroy the payload.
29
29
  * @param {Constructor | undefined} type The details type to deserialize into, or `undefined` to leave
30
30
  * the payload untouched.
31
- * @param {unknown} details The raw details payload - parsed JSON from the identity cookie or the
32
- * `/.cratis/me` endpoint.
31
+ * @param {unknown} details The raw details payload - parsed JSON from the `/.cratis/me` endpoint.
33
32
  * @returns {unknown} The deserialized instance, or `details` unchanged when deserializing it would be
34
33
  * unsafe, pointless, or has already been done.
35
34
  * @remarks
@@ -1 +1 @@
1
- {"version":3,"file":"deserializeIdentityDetails.js","sources":["../../../identity/deserializeIdentityDetails.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, Fields, JsonSerializer } from '@cratis/fundamentals';\n\n/*\n * ⚠️ deserializeIdentityDetails is exported deliberately, unlike deserializeQueryModel in\n * ../queries/deserializeQueryModel.ts.\n *\n * JsonSerializer's converter registry is module state, and a consumer package can easily resolve a\n * different physical copy of @cratis/fundamentals than this one - which is why deserializeQueryModel\n * stays package-private. Identity details are different: @cratis/arc.react's useIdentity() needs to\n * apply the exact same deserialization as this package's own IdentityProvider, for a payload that may\n * already be flowing through this package's IdentityProvider/IIdentity. Exporting the function itself\n * - rather than having @cratis/arc.react re-implement the same logic against its own copy of\n * @cratis/fundamentals - guarantees every identity details value is deserialized through this one\n * physical JsonSerializer/Fields, regardless of which package's copy of @cratis/fundamentals the\n * caller resolved.\n */\n\n/**\n * Determines whether a details type is a JavaScript primitive wrapper rather than a real,\n * `@field`-decorated model.\n * @param {Constructor} type The details type to check.\n * @returns {boolean} True when the type is a primitive wrapper.\n */\nfunction isPrimitiveDetailsType(type: Constructor): boolean {\n return type === String || type === Number || type === Boolean;\n}\n\n/**\n * Deserializes identity details into their strongly-typed shape, guarding every way that doing so\n * would otherwise crash or silently destroy the payload.\n * @param {Constructor | undefined} type The details type to deserialize into, or `undefined` to leave\n * the payload untouched.\n * @param {unknown} details The raw details payload - parsed JSON from the identity cookie or the\n * `/.cratis/me` endpoint.\n * @returns {unknown} The deserialized instance, or `details` unchanged when deserializing it would be\n * unsafe, pointless, or has already been done.\n * @remarks\n * {@link JsonSerializer.deserializeFromInstance} assumes a well-formed object and a target type\n * carrying `@field` metadata - neither is guaranteed here:\n * - No type means there is nothing to deserialize into.\n * - A `null`/`undefined`/non-object payload would make `deserializeFromInstance`'s internal\n * `instance[field.name]` lookup throw.\n * - A payload that is already an instance of the target type has already been deserialized -\n * deserializing it again is destructive, not merely wasteful: it can throw on a nested temporal\n * value and double-wraps a concept (`{ value: { value: '...' } }`).\n * - `Object` and the primitive wrapper types (`String`, `Number`, `Boolean`) are not real,\n * `@field`-decorated models; deserializing into them would discard the payload.\n * - A type with no `@field`-decorated members deserializes to an empty instance, silently discarding\n * the payload. That is worse than leaving the payload alone, so this warns and passes it through\n * instead - preserving data beats a hard crash for anyone upgrading with an undecorated type.\n */\nexport function deserializeIdentityDetails(type: Constructor | undefined, details: unknown): unknown {\n if (!type || type === Object || isPrimitiveDetailsType(type)) {\n return details;\n }\n\n if (details === null || details === undefined || typeof details !== 'object') {\n return details;\n }\n\n if (details instanceof type) {\n return details;\n }\n\n const fields = Fields.getFieldsForType(type);\n if (fields.length === 0) {\n console.warn(\n `Identity details type '${type.name}' has no @field-decorated members. Deserializing into ` +\n 'it would discard the payload and return an empty instance, so the raw payload is being ' +\n 'passed through instead. Add @field decorators for every property that should be ' +\n 'populated, or omit the details type to receive the raw payload as-is.');\n return details;\n }\n\n return JsonSerializer.deserializeFromInstance(type as Constructor<object>, details);\n}\n"],"names":["isPrimitiveDetailsType","type","String","Number","Boolean","deserializeIdentityDetails","details","Object","undefined","fields","Fields","getFieldsForType","length","console","warn","name","JsonSerializer","deserializeFromInstance"],"mappings":";;AAAA;AACA;AAIA;;;;;;;;;;;;;;;;;;IAqBA,SAASA,uBAAuBC,IAAiB,EAAA;AAC7C,IAAA,OAAOA,IAAAA,KAASC,MAAAA,IAAUD,IAAAA,KAASE,MAAAA,IAAUF,IAAAA,KAASG,OAAAA;AAC1D;AAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBC,IACM,SAASC,0BAAAA,CAA2BJ,IAA6B,EAAEK,OAAgB,EAAA;AACtF,IAAA,IAAI,CAACL,IAAAA,IAAQA,IAAAA,KAASM,MAAAA,IAAUP,uBAAuBC,IAAAA,CAAAA,EAAO;QAC1D,OAAOK,OAAAA;AACX,IAAA;AAEA,IAAA,IAAIA,YAAY,IAAA,IAAQA,OAAAA,KAAYE,SAAAA,IAAa,OAAOF,YAAY,QAAA,EAAU;QAC1E,OAAOA,OAAAA;AACX,IAAA;AAEA,IAAA,IAAIA,mBAAmBL,IAAAA,EAAM;QACzB,OAAOK,OAAAA;AACX,IAAA;IAEA,MAAMG,MAAAA,GAASC,MAAAA,CAAOC,gBAAgB,CAACV,IAAAA,CAAAA;IACvC,IAAIQ,MAAAA,CAAOG,MAAM,KAAK,CAAA,EAAG;AACrBC,QAAAA,OAAAA,CAAQC,IAAI,CACR,CAAC,uBAAuB,EAAEb,IAAAA,CAAKc,IAAI,CAAC,sDAAsD,CAAC,GAC3F,yFAAA,GACA,kFAAA,GACA,uEAAA,CAAA;QACJ,OAAOT,OAAAA;AACX,IAAA;IAEA,OAAOU,cAAAA,CAAeC,uBAAuB,CAAChB,IAAAA,EAA6BK,OAAAA,CAAAA;AAC/E;;"}
1
+ {"version":3,"file":"deserializeIdentityDetails.js","sources":["../../../identity/deserializeIdentityDetails.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, Fields, JsonSerializer } from '@cratis/fundamentals';\n\n/*\n * ⚠️ deserializeIdentityDetails is exported deliberately, unlike deserializeQueryModel in\n * ../queries/deserializeQueryModel.ts.\n *\n * JsonSerializer's converter registry is module state, and a consumer package can easily resolve a\n * different physical copy of @cratis/fundamentals than this one - which is why deserializeQueryModel\n * stays package-private. Identity details are different: @cratis/arc.react's useIdentity() needs to\n * apply the exact same deserialization as this package's own IdentityProvider, for a payload that may\n * already be flowing through this package's IdentityProvider/IIdentity. Exporting the function itself\n * - rather than having @cratis/arc.react re-implement the same logic against its own copy of\n * @cratis/fundamentals - guarantees every identity details value is deserialized through this one\n * physical JsonSerializer/Fields, regardless of which package's copy of @cratis/fundamentals the\n * caller resolved.\n */\n\n/**\n * Determines whether a details type is a JavaScript primitive wrapper rather than a real,\n * `@field`-decorated model.\n * @param {Constructor} type The details type to check.\n * @returns {boolean} True when the type is a primitive wrapper.\n */\nfunction isPrimitiveDetailsType(type: Constructor): boolean {\n return type === String || type === Number || type === Boolean;\n}\n\n/**\n * Deserializes identity details into their strongly-typed shape, guarding every way that doing so\n * would otherwise crash or silently destroy the payload.\n * @param {Constructor | undefined} type The details type to deserialize into, or `undefined` to leave\n * the payload untouched.\n * @param {unknown} details The raw details payload - parsed JSON from the `/.cratis/me` endpoint.\n * @returns {unknown} The deserialized instance, or `details` unchanged when deserializing it would be\n * unsafe, pointless, or has already been done.\n * @remarks\n * {@link JsonSerializer.deserializeFromInstance} assumes a well-formed object and a target type\n * carrying `@field` metadata - neither is guaranteed here:\n * - No type means there is nothing to deserialize into.\n * - A `null`/`undefined`/non-object payload would make `deserializeFromInstance`'s internal\n * `instance[field.name]` lookup throw.\n * - A payload that is already an instance of the target type has already been deserialized -\n * deserializing it again is destructive, not merely wasteful: it can throw on a nested temporal\n * value and double-wraps a concept (`{ value: { value: '...' } }`).\n * - `Object` and the primitive wrapper types (`String`, `Number`, `Boolean`) are not real,\n * `@field`-decorated models; deserializing into them would discard the payload.\n * - A type with no `@field`-decorated members deserializes to an empty instance, silently discarding\n * the payload. That is worse than leaving the payload alone, so this warns and passes it through\n * instead - preserving data beats a hard crash for anyone upgrading with an undecorated type.\n */\nexport function deserializeIdentityDetails(type: Constructor | undefined, details: unknown): unknown {\n if (!type || type === Object || isPrimitiveDetailsType(type)) {\n return details;\n }\n\n if (details === null || details === undefined || typeof details !== 'object') {\n return details;\n }\n\n if (details instanceof type) {\n return details;\n }\n\n const fields = Fields.getFieldsForType(type);\n if (fields.length === 0) {\n console.warn(\n `Identity details type '${type.name}' has no @field-decorated members. Deserializing into ` +\n 'it would discard the payload and return an empty instance, so the raw payload is being ' +\n 'passed through instead. Add @field decorators for every property that should be ' +\n 'populated, or omit the details type to receive the raw payload as-is.');\n return details;\n }\n\n return JsonSerializer.deserializeFromInstance(type as Constructor<object>, details);\n}\n"],"names":["isPrimitiveDetailsType","type","String","Number","Boolean","deserializeIdentityDetails","details","Object","undefined","fields","Fields","getFieldsForType","length","console","warn","name","JsonSerializer","deserializeFromInstance"],"mappings":";;AAAA;AACA;AAIA;;;;;;;;;;;;;;;;;;IAqBA,SAASA,uBAAuBC,IAAiB,EAAA;AAC7C,IAAA,OAAOA,IAAAA,KAASC,MAAAA,IAAUD,IAAAA,KAASE,MAAAA,IAAUF,IAAAA,KAASG,OAAAA;AAC1D;AAEA;;;;;;;;;;;;;;;;;;;;;;AAsBC,IACM,SAASC,0BAAAA,CAA2BJ,IAA6B,EAAEK,OAAgB,EAAA;AACtF,IAAA,IAAI,CAACL,IAAAA,IAAQA,IAAAA,KAASM,MAAAA,IAAUP,uBAAuBC,IAAAA,CAAAA,EAAO;QAC1D,OAAOK,OAAAA;AACX,IAAA;AAEA,IAAA,IAAIA,YAAY,IAAA,IAAQA,OAAAA,KAAYE,SAAAA,IAAa,OAAOF,YAAY,QAAA,EAAU;QAC1E,OAAOA,OAAAA;AACX,IAAA;AAEA,IAAA,IAAIA,mBAAmBL,IAAAA,EAAM;QACzB,OAAOK,OAAAA;AACX,IAAA;IAEA,MAAMG,MAAAA,GAASC,MAAAA,CAAOC,gBAAgB,CAACV,IAAAA,CAAAA;IACvC,IAAIQ,MAAAA,CAAOG,MAAM,KAAK,CAAA,EAAG;AACrBC,QAAAA,OAAAA,CAAQC,IAAI,CACR,CAAC,uBAAuB,EAAEb,IAAAA,CAAKc,IAAI,CAAC,sDAAsD,CAAC,GAC3F,yFAAA,GACA,kFAAA,GACA,uEAAA,CAAA;QACJ,OAAOT,OAAAA;AACX,IAAA;IAEA,OAAOU,cAAAA,CAAeC,uBAAuB,CAAChB,IAAAA,EAA6BK,OAAAA,CAAAA;AAC/E;;"}
@@ -0,0 +1,11 @@
1
+ import { an_identity_provider } from './an_identity_provider.js';
2
+ export declare class a_browser_with_a_legacy_identity extends an_identity_provider {
3
+ private browser;
4
+ private originalDocument;
5
+ private originalLocation;
6
+ protected browserUrl: string;
7
+ get cookieJar(): import("jsdom").CookieJar;
8
+ constructor();
9
+ reload(): void;
10
+ }
11
+ //# sourceMappingURL=a_browser_with_a_legacy_identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a_browser_with_a_legacy_identity.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGjE,qBAAa,gCAAiC,SAAQ,oBAAoB;IACtE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,SAAS,CAAC,UAAU,SAAkC;IAEtD,IAAI,SAAS,8BAEZ;IAED,cAkBC;IAED,MAAM,IAAI,IAAI,CAOb;CACJ"}
@@ -0,0 +1,42 @@
1
+ import { JSDOM } from 'jsdom';
2
+ import { an_identity_provider } from './an_identity_provider.js';
3
+ import { IdentityProvider } from '../../IdentityProvider.js';
4
+ export class a_browser_with_a_legacy_identity extends an_identity_provider {
5
+ browser;
6
+ originalDocument;
7
+ originalLocation;
8
+ browserUrl = 'http://localhost/nested/page';
9
+ get cookieJar() {
10
+ return this.browser.cookieJar;
11
+ }
12
+ constructor() {
13
+ super();
14
+ beforeEach(() => {
15
+ this.originalDocument = document;
16
+ this.originalLocation = global.location;
17
+ this.browser = new JSDOM('', { url: this.browserUrl });
18
+ global.document = this.browser.window.document;
19
+ global.location = this.browser.window.location;
20
+ document.cookie = `.cratis-identity=${btoa(JSON.stringify({ id: 'user-123', name: 'Original User', roles: ['Reader'], details: {} }))};path=/;samesite=lax${location.protocol === 'https:' ? ';secure' : ''}`;
21
+ this.fetchStub.resolves({ ok: false, status: 404 });
22
+ });
23
+ afterEach(() => {
24
+ IdentityProvider.clearCache();
25
+ this.browser.window.close();
26
+ global.document = this.originalDocument;
27
+ if (this.originalLocation)
28
+ global.location = this.originalLocation;
29
+ else
30
+ delete global.location;
31
+ });
32
+ }
33
+ reload() {
34
+ const cookieJar = this.browser.cookieJar;
35
+ const url = this.browser.window.location.href;
36
+ this.browser.window.close();
37
+ this.browser = new JSDOM('', { url, cookieJar });
38
+ global.document = this.browser.window.document;
39
+ global.location = this.browser.window.location;
40
+ }
41
+ }
42
+ //# sourceMappingURL=a_browser_with_a_legacy_identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a_browser_with_a_legacy_identity.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,MAAM,OAAO,gCAAiC,SAAQ,oBAAoB;IAC9D,OAAO,CAAS;IAChB,gBAAgB,CAAY;IAC5B,gBAAgB,CAAuB;IACrC,UAAU,GAAG,8BAA8B,CAAC;IAEtD,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;IAClC,CAAC;IAED;QACI,KAAK,EAAE,CAAC;QACR,UAAU,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;YACjC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC;YACxC,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACvD,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC/C,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC/C,QAAQ,CAAC,MAAM,GAAG,oBAAoB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,uBAAuB,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC9M,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,GAAG,EAAE;YACX,gBAAgB,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;YACxC,IAAI,IAAI,CAAC,gBAAgB;gBAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;;gBAC9D,OAAQ,MAAkC,CAAC,QAAQ,CAAC;QAC7D,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM;QACF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC/C,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;IACnD,CAAC;CACJ"}
@@ -0,0 +1,7 @@
1
+ import { an_identity_provider } from './an_identity_provider.js';
2
+ import { IdentityProviderResult } from '../../IdentityProviderResult.js';
3
+ export declare class a_cookie_first_backend extends an_identity_provider {
4
+ currentIdentity: IdentityProviderResult | undefined;
5
+ constructor();
6
+ }
7
+ //# sourceMappingURL=a_cookie_first_backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a_cookie_first_backend.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/a_cookie_first_backend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,qBAAa,sBAAuB,SAAQ,oBAAoB;IAC5D,eAAe,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAEpD,cAcC;CACJ"}
@@ -0,0 +1,19 @@
1
+ import { an_identity_provider } from './an_identity_provider.js';
2
+ export class a_cookie_first_backend extends an_identity_provider {
3
+ currentIdentity;
4
+ constructor() {
5
+ super();
6
+ beforeEach(() => {
7
+ this.currentIdentity = { id: 'user-123', name: 'Original User', roles: ['Reader'], details: { department: 'Original' } };
8
+ document.cookie = `.cratis-identity=${btoa(JSON.stringify(this.currentIdentity))}`;
9
+ this.fetchStub.callsFake(async () => {
10
+ const encodedCookie = document.cookie.split(';').map(_ => _.trim()).find(_ => _.startsWith('.cratis-identity='))?.substring('.cratis-identity='.length);
11
+ const identity = encodedCookie ? JSON.parse(atob(encodedCookie)) : this.currentIdentity;
12
+ return identity
13
+ ? { ok: true, status: 200, json: async () => identity }
14
+ : { ok: false, status: 401 };
15
+ });
16
+ });
17
+ }
18
+ }
19
+ //# sourceMappingURL=a_cookie_first_backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a_cookie_first_backend.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/a_cookie_first_backend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGjE,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IAC5D,eAAe,CAAqC;IAEpD;QACI,KAAK,EAAE,CAAC;QACR,UAAU,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,eAAe,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC;YACzH,QAAQ,CAAC,MAAM,GAAG,oBAAoB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;YACnF,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;gBAEhC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;gBACxJ,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;gBACxF,OAAO,QAAQ;oBACX,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ,EAAc;oBACnE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC;YACjD,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;CACJ"}
@@ -0,0 +1,5 @@
1
+ import { a_browser_with_a_legacy_identity } from './a_browser_with_a_legacy_identity.js';
2
+ export declare class a_secure_browser_with_a_legacy_identity extends a_browser_with_a_legacy_identity {
3
+ protected browserUrl: string;
4
+ }
5
+ //# sourceMappingURL=a_secure_browser_with_a_legacy_identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a_secure_browser_with_a_legacy_identity.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AAEzF,qBAAa,uCAAwC,SAAQ,gCAAgC;IACzF,SAAS,CAAC,UAAU,SAA0C;CACjE"}
@@ -0,0 +1,5 @@
1
+ import { a_browser_with_a_legacy_identity } from './a_browser_with_a_legacy_identity.js';
2
+ export class a_secure_browser_with_a_legacy_identity extends a_browser_with_a_legacy_identity {
3
+ browserUrl = 'https://identity.example/nested/page';
4
+ }
5
+ //# sourceMappingURL=a_secure_browser_with_a_legacy_identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a_secure_browser_with_a_legacy_identity.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AAEzF,MAAM,OAAO,uCAAwC,SAAQ,gCAAgC;IAC/E,UAAU,GAAG,sCAAsC,CAAC;CACjE"}
@@ -8,5 +8,6 @@ export declare class an_identity_provider {
8
8
  originalApiBasePath: string;
9
9
  originalOrigin: string;
10
10
  constructor();
11
+ serverReports(identity: object): void;
11
12
  }
12
13
  //# sourceMappingURL=an_identity_provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"an_identity_provider.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/an_identity_provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,qBAAa,oBAAoB;IAC7B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,WAAW,EAAE;QAAE,SAAS,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACvE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IAEvB,cAgBC;CACJ"}
1
+ {"version":3,"file":"an_identity_provider.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/an_identity_provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,qBAAa,oBAAoB;IAC7B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,WAAW,EAAE;QAAE,SAAS,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACvE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IAEvB,cAwBC;IAMD,aAAa,CAAC,QAAQ,EAAE,MAAM,QAK7B;CACJ"}
@@ -18,6 +18,17 @@ export class an_identity_provider {
18
18
  }
19
19
  this.fetchHelper = createFetchHelper();
20
20
  this.fetchStub = this.fetchHelper.stubFetch();
21
+ beforeEach(() => {
22
+ global.document.cookie = '';
23
+ IdentityProvider.clearCache();
24
+ this.fetchStub.resetHistory();
25
+ });
26
+ }
27
+ serverReports(identity) {
28
+ this.fetchStub.resolves({
29
+ ok: true,
30
+ json: async () => identity
31
+ });
21
32
  }
22
33
  }
23
34
  //# sourceMappingURL=an_identity_provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"an_identity_provider.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/an_identity_provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,MAAM,OAAO,oBAAoB;IAC7B,SAAS,CAAkB;IAC3B,WAAW,CAA4D;IACvE,mBAAmB,CAAS;IAC5B,cAAc,CAAS;IAEvB;QACI,IAAI,CAAC,mBAAmB,GAAG,gBAAgB,CAAC,WAAW,CAAC;QACxD,IAAI,CAAC,cAAc,GAAG,gBAAgB,CAAC,MAAM,CAAC;QAG9C,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACjC,MAA0E,CAAC,QAAQ,GAAG;gBACnF,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE;oBACN,MAAM,EAAE,kBAAkB;iBAC7B;aACJ,CAAC;QACN,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,iBAAiB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;IAClD,CAAC;CACJ"}
1
+ {"version":3,"file":"an_identity_provider.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/given/an_identity_provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,MAAM,OAAO,oBAAoB;IAC7B,SAAS,CAAkB;IAC3B,WAAW,CAA4D;IACvE,mBAAmB,CAAS;IAC5B,cAAc,CAAS;IAEvB;QACI,IAAI,CAAC,mBAAmB,GAAG,gBAAgB,CAAC,WAAW,CAAC;QACxD,IAAI,CAAC,cAAc,GAAG,gBAAgB,CAAC,MAAM,CAAC;QAG9C,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACjC,MAA0E,CAAC,QAAQ,GAAG;gBACnF,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE;oBACN,MAAM,EAAE,kBAAkB;iBAC7B;aACJ,CAAC;QACN,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,iBAAiB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QAI9C,UAAU,CAAC,GAAG,EAAE;YACX,MAA4C,CAAC,QAAS,CAAC,MAAM,GAAG,EAAE,CAAC;YACpE,gBAAgB,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QAClC,CAAC,CAAC,CAAC;IACP,CAAC;IAMD,aAAa,CAAC,QAAgB;QAC1B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;YACpB,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ;SACjB,CAAC,CAAC;IACnB,CAAC;CACJ"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=after_a_legacy_refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_a_legacy_refresh.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import { IdentityProvider } from '../../IdentityProvider.js';
2
+ import { a_browser_with_a_legacy_identity } from '../given/a_browser_with_a_legacy_identity.js';
3
+ import { given } from '../../../given.js';
4
+ describe('when clearing cache after a legacy refresh', given(a_browser_with_a_legacy_identity, context => {
5
+ let identity;
6
+ beforeEach(async () => {
7
+ await IdentityProvider.refresh();
8
+ IdentityProvider.clearCache();
9
+ identity = await IdentityProvider.getCurrent();
10
+ });
11
+ it('should ask the server again', () => context.fetchStub.calledTwice.should.be.true);
12
+ it('should discard the retained transition identity', () => identity.isSet.should.be.false);
13
+ it('should leave the legacy cookie expired', () => document.cookie.should.equal(''));
14
+ }));
15
+ //# sourceMappingURL=after_a_legacy_refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_a_legacy_refresh.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,gCAAgC,EAAE,MAAM,8CAA8C,CAAC;AAChG,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,QAAQ,CAAC,4CAA4C,EAAE,KAAK,CAAC,gCAAgC,EAAE,OAAO,CAAC,EAAE;IACrG,IAAI,QAAmB,CAAC;IAExB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC;QACjC,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAC9B,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACtF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC5F,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AACzF,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=when_clearing_cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when_clearing_cache.d.ts","sourceRoot":"","sources":["../../../../identity/for_IdentityProvider/when_clearing_cache.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import { IdentityProvider } from '../IdentityProvider.js';
2
+ import { an_identity_provider } from './given/an_identity_provider.js';
3
+ import { given } from '../../given.js';
4
+ describe('when clearing cache', given(an_identity_provider, context => {
5
+ let identity;
6
+ beforeEach(async () => {
7
+ context.serverReports({ id: 'user-123', name: 'Test User', roles: [], details: {} });
8
+ await IdentityProvider.getCurrent();
9
+ IdentityProvider.clearCache();
10
+ context.fetchStub.resolves({ ok: false, status: 401 });
11
+ identity = await IdentityProvider.getCurrent();
12
+ });
13
+ it('should ask the server again', () => context.fetchStub.calledTwice.should.be.true);
14
+ it('should report what the server reports now', () => identity.isSet.should.be.false);
15
+ it('should expire a legacy identity cookie', () => global.document.cookie.should.contain('.cratis-identity=;expires=Thu, 01 Jan 1970'));
16
+ }));
17
+ //# sourceMappingURL=when_clearing_cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when_clearing_cache.js","sourceRoot":"","sources":["../../../../identity/for_IdentityProvider/when_clearing_cache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,QAAQ,CAAC,qBAAqB,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IAClE,IAAI,QAAmB,CAAC;IAExB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QACrF,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAEpC,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAC9B,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC,CAAC;QACnE,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACtF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACtF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE,CAAE,MAA4C,CAAC,QAAS,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAC,CAAC;AACpL,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=after_reloading_a_legacy_refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_reloading_a_legacy_refresh.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { vi } from 'vitest';
2
+ import { IdentityProvider } from '../../IdentityProvider.js';
3
+ import { a_browser_with_a_legacy_identity } from '../given/a_browser_with_a_legacy_identity.js';
4
+ import { given } from '../../../given.js';
5
+ describe('when getting current after reloading a legacy refresh', given(a_browser_with_a_legacy_identity, context => {
6
+ let identity;
7
+ beforeEach(async () => {
8
+ await IdentityProvider.refresh();
9
+ context.reload();
10
+ vi.resetModules();
11
+ const { IdentityProvider: reloadedProvider } = await import('../../IdentityProvider.js');
12
+ identity = await reloadedProvider.getCurrent();
13
+ });
14
+ it('should ask the server again after the reload', () => context.fetchStub.calledTwice.should.be.true);
15
+ it('should preserve the transition identity across the reload', () => identity.id.should.equal('user-123'));
16
+ it('should preserve the transition roles across the reload', () => identity.isInRole('Reader').should.be.true);
17
+ }));
18
+ //# sourceMappingURL=after_reloading_a_legacy_refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_reloading_a_legacy_refresh.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,gCAAgC,EAAE,MAAM,8CAA8C,CAAC;AAChG,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,QAAQ,CAAC,uDAAuD,EAAE,KAAK,CAAC,gCAAgC,EAAE,OAAO,CAAC,EAAE;IAChH,IAAI,QAAmB,CAAC;IAExB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACzF,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACvG,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAC5G,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AACnH,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=after_the_server_did_not_resolve_an_identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_the_server_did_not_resolve_an_identity.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ import { IdentityProvider } from '../../IdentityProvider.js';
2
+ import { an_identity_provider } from '../given/an_identity_provider.js';
3
+ import { given } from '../../../given.js';
4
+ describe('when getting current after the server did not resolve an identity', given(an_identity_provider, context => {
5
+ let first;
6
+ let second;
7
+ beforeEach(async () => {
8
+ context.fetchStub.onFirstCall().resolves({ ok: false, status: 401 });
9
+ context.fetchStub.onSecondCall().resolves({
10
+ ok: true,
11
+ json: async () => ({ id: 'user-123', name: 'Test User', roles: [], details: {} })
12
+ });
13
+ first = await IdentityProvider.getCurrent();
14
+ second = await IdentityProvider.getCurrent();
15
+ });
16
+ it('should report the first identity as not set', () => first.isSet.should.be.false);
17
+ it('should ask the server again', () => context.fetchStub.calledTwice.should.be.true);
18
+ it('should report the identity the server resolved', () => second.id.should.equal('user-123'));
19
+ }));
20
+ //# sourceMappingURL=after_the_server_did_not_resolve_an_identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_the_server_did_not_resolve_an_identity.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAM1C,QAAQ,CAAC,mEAAmE,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IAChH,IAAI,KAAgB,CAAC;IACrB,IAAI,MAAiB,CAAC;IAEtB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC,CAAC;QACjF,OAAO,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC;YACtC,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;SACxE,CAAC,CAAC;QAEf,KAAK,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACrF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACtF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AACnG,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=and_the_server_has_no_identity_endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"and_the_server_has_no_identity_endpoint.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { IdentityProvider } from '../../IdentityProvider.js';
2
+ import { an_identity_provider } from '../given/an_identity_provider.js';
3
+ import { given } from '../../../given.js';
4
+ describe('when getting current and the server has no identity endpoint', given(an_identity_provider, context => {
5
+ let identity;
6
+ let warnings;
7
+ let originalConsoleWarn;
8
+ beforeEach(async () => {
9
+ warnings = [];
10
+ originalConsoleWarn = console.warn;
11
+ console.warn = (...args) => { warnings.push(args); };
12
+ IdentityProvider.hasWarnedAboutLegacyCookie = false;
13
+ const cookie = btoa(JSON.stringify({ id: 'user-123', name: 'Test User', roles: ['Reader'], details: {} }));
14
+ global.document.cookie = `.cratis-identity=${cookie}`;
15
+ context.fetchStub.resolves({ ok: false, status: 404 });
16
+ identity = await IdentityProvider.getCurrent();
17
+ });
18
+ afterEach(() => { console.warn = originalConsoleWarn; });
19
+ it('should ask the server first', () => context.fetchStub.calledOnce.should.be.true);
20
+ it('should report the identity from the cookie', () => identity.id.should.equal('user-123'));
21
+ it('should report the roles from the cookie', () => identity.isInRole('Reader').should.be.true);
22
+ it('should warn that the cookie was read', () => warnings.length.should.equal(1));
23
+ }));
24
+ //# sourceMappingURL=and_the_server_has_no_identity_endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"and_the_server_has_no_identity_endpoint.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,QAAQ,CAAC,8DAA8D,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IAC3G,IAAI,QAAmB,CAAC;IACxB,IAAI,QAAqB,CAAC;IAC1B,IAAI,mBAAwC,CAAC;IAE7C,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,QAAQ,GAAG,EAAE,CAAC;QACd,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;QACnC,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,gBAAuE,CAAC,0BAA0B,GAAG,KAAK,CAAC;QAE5G,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC1G,MAA4C,CAAC,QAAS,CAAC,MAAM,GAAG,oBAAoB,MAAM,EAAE,CAAC;QAC9F,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC,CAAC;QAEnE,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACrF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7F,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAChG,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=and_the_server_rejects_the_caller_with_a_forged_identity_cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"and_the_server_rejects_the_caller_with_a_forged_identity_cookie.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { IdentityProvider } from '../../IdentityProvider.js';
2
+ import { an_identity_provider } from '../given/an_identity_provider.js';
3
+ import { given } from '../../../given.js';
4
+ describe('when getting current and the server rejects the caller with a forged identity cookie', given(an_identity_provider, context => {
5
+ let identity;
6
+ beforeEach(async () => {
7
+ const forged = btoa(JSON.stringify({ id: 'admin', name: 'Forged Administrator', roles: ['admin'], details: {} }));
8
+ global.document.cookie = `.cratis-identity=${forged}`;
9
+ context.fetchStub.resolves({ ok: false, status: 401 });
10
+ identity = await IdentityProvider.getCurrent();
11
+ });
12
+ it('should not be set', () => identity.isSet.should.be.false);
13
+ it('should not report the forged identity', () => identity.id.should.equal(''));
14
+ it('should not report the forged role', () => identity.isInRole('admin').should.be.false);
15
+ }));
16
+ //# sourceMappingURL=and_the_server_rejects_the_caller_with_a_forged_identity_cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"and_the_server_rejects_the_caller_with_a_forged_identity_cookie.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,QAAQ,CAAC,sFAAsF,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IACnI,IAAI,QAAmB,CAAC;IAExB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACjH,MAA4C,CAAC,QAAS,CAAC,MAAM,GAAG,oBAAoB,MAAM,EAAE,CAAC;QAC9F,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC,CAAC;QAEnE,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9D,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAChF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=twice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twice.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/twice.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import { IdentityProvider } from '../../IdentityProvider.js';
2
+ import { an_identity_provider } from '../given/an_identity_provider.js';
3
+ import { given } from '../../../given.js';
4
+ describe('when getting current twice', given(an_identity_provider, context => {
5
+ let first;
6
+ let second;
7
+ beforeEach(async () => {
8
+ context.serverReports({ id: 'user-123', name: 'Test User', roles: [], details: {} });
9
+ first = await IdentityProvider.getCurrent();
10
+ second = await IdentityProvider.getCurrent();
11
+ });
12
+ it('should ask the server only once', () => context.fetchStub.calledOnce.should.be.true);
13
+ it('should report the same identity both times', () => second.id.should.equal(first.id));
14
+ }));
15
+ //# sourceMappingURL=twice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twice.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/twice.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,QAAQ,CAAC,4BAA4B,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IACzE,IAAI,KAAgB,CAAC;IACrB,IAAI,MAAiB,CAAC;IAEtB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAErF,KAAK,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACzF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7F,CAAC,CAAC,CAAC,CAAC"}
@@ -5,7 +5,7 @@ class UndecoratedDetails {
5
5
  userId;
6
6
  role;
7
7
  }
8
- describe('when getting current with a details type that declares no fields', given(an_identity_provider, () => {
8
+ describe('when getting current with a details type that declares no fields', given(an_identity_provider, context => {
9
9
  let originalConsoleWarn;
10
10
  let result;
11
11
  beforeEach(async () => {
@@ -19,8 +19,7 @@ describe('when getting current with a details type that declares no fields', giv
19
19
  role: 'admin'
20
20
  }
21
21
  };
22
- const encodedData = btoa(JSON.stringify(identityData));
23
- global.document.cookie = `.cratis-identity=${encodedData}`;
22
+ context.serverReports(identityData);
24
23
  const identity = await IdentityProvider.getCurrent(UndecoratedDetails);
25
24
  result = { details: identity.details };
26
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"with_a_details_type_that_declares_no_fields.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C,MAAM,kBAAkB;IACpB,MAAM,CAAU;IAChB,IAAI,CAAU;CACjB;AAED,QAAQ,CAAC,kEAAkE,EAAE,KAAK,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAC1G,IAAI,mBAAwC,CAAC;IAC7C,IAAI,MAAuC,CAAC;IAE5C,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;QACnC,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,GAAgC,CAAC,CAAC;QAEtD,MAAM,YAAY,GAAG;YACjB,EAAE,EAAE,cAAc;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE;gBACL,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,OAAO;aAChB;SACJ,CAAC;QACF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;QACtD,MAA4C,CAAC,QAAS,CAAC,MAAM,GAAG,oBAAoB,WAAW,EAAE,CAAC;QAEnG,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;QACvE,MAAM,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,OAAyC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,OAAuC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"with_a_details_type_that_declares_no_fields.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C,MAAM,kBAAkB;IACpB,MAAM,CAAU;IAChB,IAAI,CAAU;CACjB;AAED,QAAQ,CAAC,kEAAkE,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IAC/G,IAAI,mBAAwC,CAAC;IAC7C,IAAI,MAAuC,CAAC;IAE5C,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;QACnC,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,GAAgC,CAAC,CAAC;QAEtD,MAAM,YAAY,GAAG;YACjB,EAAE,EAAE,cAAc;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE;gBACL,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,OAAO;aAChB;SACJ,CAAC;QACF,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAEpC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;QACvE,MAAM,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,OAAyC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,OAAuC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_a_forged_identity_cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_a_forged_identity_cookie.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { IdentityProvider } from '../../IdentityProvider.js';
2
+ import { an_identity_provider } from '../given/an_identity_provider.js';
3
+ import { given } from '../../../given.js';
4
+ describe('when getting current with a forged identity cookie', given(an_identity_provider, context => {
5
+ let identity;
6
+ beforeEach(async () => {
7
+ const forged = btoa(JSON.stringify({ id: 'admin', name: 'Forged Administrator', roles: ['admin'], details: {} }));
8
+ global.document.cookie = `.cratis-identity=${forged}`;
9
+ context.serverReports({ id: 'user-123', name: 'Test User', roles: ['Reader'], details: {} });
10
+ identity = await IdentityProvider.getCurrent();
11
+ });
12
+ it('should ask the server', () => context.fetchStub.calledOnce.should.be.true);
13
+ it('should ask the identity endpoint', () => String(context.fetchStub.firstCall.args[0]).should.contain('/.cratis/me'));
14
+ it('should report the identity the server reported', () => identity.id.should.equal('user-123'));
15
+ it('should report the roles the server reported', () => identity.roles.should.deep.equal(['Reader']));
16
+ it('should not report the forged role', () => identity.isInRole('admin').should.be.false);
17
+ }));
18
+ //# sourceMappingURL=with_a_forged_identity_cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_a_forged_identity_cookie.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAM1C,QAAQ,CAAC,oDAAoD,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IACjG,IAAI,QAAmB,CAAC;IAExB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACjH,MAA4C,CAAC,QAAS,CAAC,MAAM,GAAG,oBAAoB,MAAM,EAAE,CAAC;QAC9F,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAE7F,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAC/E,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IACxH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IACjG,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtG,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC,CAAC"}