@@ -11,6 +11,8 @@
|
||||
"./element-api": "./dist-cms/libs/element-api/index.js",
|
||||
"./extension-api": "./dist-cms/libs/extension-api/index.js",
|
||||
"./observable-api": "./dist-cms/libs/observable-api/index.js",
|
||||
"./auth": "./dist-cms/shared/auth/index.js",
|
||||
"./context": "./dist-cms/shared/context/index.js",
|
||||
"./events": "./dist-cms/shared/umb-events/index.js",
|
||||
"./models": "./dist-cms/shared/models/index.js",
|
||||
"./repository": "./dist-cms/shared/repository/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UMB_AUTH, UmbAuthFlow } from '@umbraco-cms/backoffice/auth';
|
||||
import { UMB_APP, UmbAppContext } from '@umbraco-cms/backoffice/context';
|
||||
import type { UmbAppErrorElement } from './app-error.element.js';
|
||||
import { UmbAuthFlow } from './auth/index.js';
|
||||
import { UMB_APP, UmbAppContext } from './app.context.js';
|
||||
import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UUIIconRegistryEssential } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbIconRegistry } from '@umbraco-cms/backoffice/icon';
|
||||
@@ -81,6 +81,8 @@ export class UmbAppElement extends UmbLitElement {
|
||||
|
||||
this.#authFlow = new UmbAuthFlow(this.serverUrl, redirectUrl);
|
||||
|
||||
this.provideContext(UMB_AUTH, this.#authFlow);
|
||||
|
||||
this.provideContext(UMB_APP, new UmbAppContext({ backofficePath: this.backofficePath, serverUrl: this.serverUrl }));
|
||||
|
||||
// Try to initialise the auth flow and get the runtime status
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './auth-flow.js';
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './app-context-config.interface.js';
|
||||
export * from './app-error.element.js';
|
||||
export * from './app.context.js';
|
||||
export * from './app.element.js';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UMB_AUTH } from '@umbraco-cms/backoffice/auth';
|
||||
import { UMB_APP } from '@umbraco-cms/backoffice/context';
|
||||
import { UmbCurrentUserStore, UMB_CURRENT_USER_STORE_CONTEXT_TOKEN } from '../../current-user.store.js';
|
||||
import type { UmbLoggedInUser } from '../../types.js';
|
||||
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
|
||||
@@ -15,6 +17,10 @@ export class UmbCurrentUserModalElement extends UmbLitElement {
|
||||
|
||||
private _currentUserStore?: UmbCurrentUserStore;
|
||||
|
||||
#auth?: typeof UMB_AUTH.TYPE;
|
||||
|
||||
#appContext?: typeof UMB_APP.TYPE;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -23,6 +29,14 @@ export class UmbCurrentUserModalElement extends UmbLitElement {
|
||||
this._observeCurrentUser();
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_AUTH, (instance) => {
|
||||
this.#auth = instance;
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_APP, (instance) => {
|
||||
this.#appContext = instance;
|
||||
});
|
||||
|
||||
this._observeCurrentUser();
|
||||
}
|
||||
|
||||
@@ -38,8 +52,13 @@ export class UmbCurrentUserModalElement extends UmbLitElement {
|
||||
this.modalContext?.submit();
|
||||
}
|
||||
|
||||
private _logout() {
|
||||
alert('implement log out');
|
||||
private async _logout() {
|
||||
if (!this.#auth) return;
|
||||
this.#auth.performWithFreshTokens;
|
||||
await this.#auth.signOut();
|
||||
let newUrl = this.#appContext ? `${this.#appContext.getBackofficePath()}/login` : '/';
|
||||
newUrl = newUrl.replace(/\/\//g, '/');
|
||||
location.href = newUrl;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
import type { IUmbAuth } from './auth.interface.js';
|
||||
import {
|
||||
BaseTokenRequestHandler,
|
||||
BasicQueryStringUtils,
|
||||
@@ -32,6 +33,8 @@ import {
|
||||
|
||||
const requestor = new FetchRequestor();
|
||||
|
||||
const TOKEN_RESPONSE_NAME = 'umb:userAuthTokenResponse';
|
||||
|
||||
/**
|
||||
* This class is needed to prevent the hash from being parsed as part of the query string.
|
||||
*/
|
||||
@@ -78,7 +81,7 @@ class UmbNoHashQueryStringUtils extends BasicQueryStringUtils {
|
||||
* a. This will redirect the user to the authorization endpoint of the server
|
||||
* 4. After login, get the latest token before each request to the server by calling the `performWithFreshTokens` method
|
||||
*/
|
||||
export class UmbAuthFlow {
|
||||
export class UmbAuthFlow implements IUmbAuth {
|
||||
// handlers
|
||||
readonly #notifier: AuthorizationNotifier;
|
||||
readonly #authorizationHandler: RedirectRequestHandler;
|
||||
@@ -155,7 +158,7 @@ export class UmbAuthFlow {
|
||||
async setInitialState() {
|
||||
// Ensure there is a connection to the server
|
||||
await this.fetchServiceConfiguration();
|
||||
const tokenResponseJson = await this.#storageBackend.getItem('tokenResponse');
|
||||
const tokenResponseJson = await this.#storageBackend.getItem(TOKEN_RESPONSE_NAME);
|
||||
if (tokenResponseJson) {
|
||||
const response = new TokenResponse(JSON.parse(tokenResponseJson));
|
||||
if (response.isValid()) {
|
||||
@@ -238,7 +241,7 @@ export class UmbAuthFlow {
|
||||
// forget all cached token state
|
||||
this.#accessTokenResponse = undefined;
|
||||
this.#refreshToken = undefined;
|
||||
await this.#storageBackend.removeItem('tokenResponse');
|
||||
await this.#storageBackend.removeItem(TOKEN_RESPONSE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,7 +285,7 @@ export class UmbAuthFlow {
|
||||
*/
|
||||
async #saveTokenState() {
|
||||
if (this.#accessTokenResponse) {
|
||||
await this.#storageBackend.setItem('tokenResponse', JSON.stringify(this.#accessTokenResponse.toJson()));
|
||||
await this.#storageBackend.setItem(TOKEN_RESPONSE_NAME, JSON.stringify(this.#accessTokenResponse.toJson()));
|
||||
}
|
||||
}
|
||||
|
||||
17
src/Umbraco.Web.UI.Client/src/shared/auth/auth.interface.ts
Normal file
17
src/Umbraco.Web.UI.Client/src/shared/auth/auth.interface.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface IUmbAuth {
|
||||
/**
|
||||
* Get the current user's access token.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* const token = await auth.getAccessToken();
|
||||
* const result = await fetch('https://my-api.com', { headers: { Authorization: `Bearer ${token}` } });
|
||||
* ```
|
||||
*/
|
||||
performWithFreshTokens(): Promise<string>;
|
||||
|
||||
/**
|
||||
* Sign out the current user.
|
||||
*/
|
||||
signOut(): Promise<void>;
|
||||
}
|
||||
10
src/Umbraco.Web.UI.Client/src/shared/auth/index.ts
Normal file
10
src/Umbraco.Web.UI.Client/src/shared/auth/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { IUmbAuth } from './auth.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export type { IUmbAuth } from './auth.interface.js';
|
||||
export { UmbAuthFlow } from './auth-flow.js';
|
||||
|
||||
export const UMB_AUTH = new UmbContextToken<IUmbAuth>(
|
||||
'UmbAuth',
|
||||
'An instance of UmbAuthFlow that should be shared across the app.'
|
||||
);
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UmbAppContextConfig } from './app-context-config.interface.js';
|
||||
import { UmbAppContextConfig } from '../../apps/app/app-context-config.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export class UmbAppContext {
|
||||
1
src/Umbraco.Web.UI.Client/src/shared/context/index.ts
Normal file
1
src/Umbraco.Web.UI.Client/src/shared/context/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './app.context.js';
|
||||
@@ -35,6 +35,8 @@
|
||||
"@umbraco-cms/backoffice/observable-api": ["src/libs/observable-api"],
|
||||
|
||||
// SHARED
|
||||
"@umbraco-cms/backoffice/auth": ["src/shared/auth"],
|
||||
"@umbraco-cms/backoffice/context": ["src/shared/context"],
|
||||
"@umbraco-cms/backoffice/events": ["src/shared/umb-events"],
|
||||
"@umbraco-cms/backoffice/models": ["src/shared/models"],
|
||||
"@umbraco-cms/backoffice/repository": ["src/shared/repository"],
|
||||
|
||||
@@ -48,6 +48,8 @@ export default {
|
||||
'@umbraco-cms/backoffice/extension-api': './src/libs/extension-api/index.ts',
|
||||
'@umbraco-cms/backoffice/observable-api': './src/libs/observable-api/index.ts',
|
||||
|
||||
'@umbraco-cms/backoffice/auth': './src/shared/auth/index.ts',
|
||||
'@umbraco-cms/backoffice/context': './src/shared/context/index.ts',
|
||||
'@umbraco-cms/backoffice/events': './src/shared/umb-events/index.ts',
|
||||
'@umbraco-cms/backoffice/models': './src/shared/models/index.ts',
|
||||
'@umbraco-cms/backoffice/repository': './src/shared/repository/index.ts',
|
||||
|
||||
Reference in New Issue
Block a user