diff --git a/src/apps/adgangsplatformen/auth.dev.jsx b/src/apps/adgangsplatformen/auth.dev.jsx deleted file mode 100644 index b494b3c604..0000000000 --- a/src/apps/adgangsplatformen/auth.dev.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import Auth from "./auth"; - -export default { - title: "SB Utilities / Adgangsplatformen" -}; - -const Template = (args) => ; - -export const SignIn = Template.bind({}); diff --git a/src/apps/adgangsplatformen/auth.jsx b/src/apps/adgangsplatformen/auth.jsx deleted file mode 100644 index 459eaf261d..0000000000 --- a/src/apps/adgangsplatformen/auth.jsx +++ /dev/null @@ -1,113 +0,0 @@ -import React, { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import fetch from "unfetch"; -import { - getToken, - setToken, - TOKEN_LIBRARY_KEY, - TOKEN_USER_KEY -} from "../../core/token"; -import { - setStatusAuthenticated, - setStatusUnauthenticated -} from "../../core/user.slice"; - -const ORIGIN = window.location.origin; -const PATHNAME = window.location.pathname.replace("/iframe.html", "/"); - -const CLIENT_ID = process.env.STORYBOOK_CLIENT_ID; -const REDIRECT_URL = `${ORIGIN}${PATHNAME}?path=/story/sb-utilities-adgangsplatformen--sign-in`; - -function Auth() { - const dispatch = useDispatch(); - const status = useSelector((s) => s.user.status); - - const handleCleanUp = useCallback(() => { - window.sessionStorage.removeItem(TOKEN_USER_KEY); - dispatch(setStatusUnauthenticated()); - }, [dispatch]); - - const handleSignIn = () => { - window.parent.location.href = `https://login.bib.dk/oauth/authorize?response_type=code&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URL}`; - }; - - const handleSignOut = () => { - handleCleanUp(); - const token = getToken(TOKEN_USER_KEY); - window.parent.location.href = `https://login.bib.dk/logout/?access_token=${token}`; - }; - - React.useEffect(() => { - const urlParams = new URLSearchParams(window.location.search); - const code = urlParams.get("code"); - - if (!code) { - return; - } - - fetch("https://login.bib.dk/oauth/token", { - method: "POST", - headers: {}, - body: new URLSearchParams({ - grant_type: "authorization_code", - code, - client_id: CLIENT_ID, - client_secret: "secret", - redirect_uri: REDIRECT_URL - }) - }) - .then((res) => res.json()) - .then((res) => { - // eslint-disable-next-line camelcase - if (!res?.access_token) { - throw res; - } - - // We need to make the token available in two contexts: - // 1. Subsequent browser reloads. Consequently we set the token into sessionstorage, which are read by preview.js. - window.sessionStorage.setItem(TOKEN_USER_KEY, res.access_token); - // 2. Current storybook context. - setToken(TOKEN_USER_KEY, res.access_token); - setToken(TOKEN_LIBRARY_KEY, res.access_token); - - dispatch(setStatusAuthenticated()); - }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error(err); - handleCleanUp(); - }); - }, [dispatch, handleCleanUp]); - - return ( -
-

Adgangsplatformen

-
- Status: - {status === "authenticated" ? ( - Signed in - ) : ( - Signed out - )} -
- -
- - - -
-
- ); -} - -export default Auth; diff --git a/src/apps/adgangsplatformen/auth.test.js b/src/apps/adgangsplatformen/auth.test.js deleted file mode 100644 index d95c94d620..0000000000 --- a/src/apps/adgangsplatformen/auth.test.js +++ /dev/null @@ -1,38 +0,0 @@ -import { TOKEN_USER_KEY } from "../../core/token"; - -describe("Authentication", () => { - beforeEach(() => { - cy.window().then((win) => { - win.sessionStorage.removeItem(TOKEN_USER_KEY); - }); - }); - it("Loads story without auth code", () => { - cy.server(); - cy.visit( - "/iframe.html?path=/story/sb-utilities-adgangsplatformen--sign-in" - ); - cy.window() - .its("sessionStorage") - .invoke("getItem", TOKEN_USER_KEY) - .should("not.exist"); - }); - it("Loads story with auth code", () => { - cy.server(); - cy.route({ - method: "POST", - url: "https://login.bib.dk/oauth/token", - status: 200, - response: { - statusCode: 200, - access_token: "random_token" - } - }); - cy.visit( - "/iframe.html?path=/story/sb-utilities-adgangsplatformen--sign-in&code=test" - ); - cy.window() - .its("sessionStorage") - .invoke("getItem", TOKEN_USER_KEY) - .should("eq", "random_token"); - }); -}); diff --git a/src/core/store.ts b/src/core/store.ts index 2380a58b9a..4871895e57 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -10,7 +10,6 @@ import { import { persistReducer, persistStore } from "redux-persist"; import storage from "redux-persist/lib/storage/session"; import textReducer from "./text.slice"; -import userReducer from "./user.slice"; import modalReducer from "./modal.slice"; import urlReducer from "./url.slice"; import filterReducer from "./filter.slice"; @@ -37,7 +36,6 @@ export const store = configureStore({ reducer: persistReducer( persistConfig, combineReducers({ - user: userReducer, text: textReducer, modal: modalReducer, url: urlReducer, diff --git a/src/core/user.js b/src/core/user.js deleted file mode 100644 index 898819b937..0000000000 --- a/src/core/user.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * A simple collection of functionality in regards to the current user. - * - * @class User - */ -import { hasToken } from "./token"; -import { store, persistor } from "./store"; -import { updateStatus, attemptAuthentication } from "./user.slice"; - -const selectStatus = (state) => state.user.status; - -class User { - /** - * Used to keep track if we started attempting in this page view. - * - * @static - */ - static #attemptingThisRequest = false; - - /** - * Returns whether a user is authenticated of not. - * - * @static - * @returns {boolean} - * @memberof User - */ - static isAuthenticated() { - store.dispatch( - updateStatus({ - hasToken: hasToken("user"), - doFail: !User.#attemptingThisRequest - }) - ); - return selectStatus(store.getState()) === "authenticated"; - } - - /** - * Redirect to login. - * - * @param {string} loginUrl the URL to redirect to. - */ - static authenticate(loginUrl) { - // Switch state to attempting and flush state to session storage - // before redirecting. - store.dispatch(attemptAuthentication()).then(() => persistor.flush()); - User.#attemptingThisRequest = true; - window.location.href = loginUrl; - } - - /** - * Whether authentication failed. - * - * Will return true if we just tried authenticating and it failed. - * - * @returns {boolean} - */ - static authenticationFailed() { - // isAuthenticated() will ensure state is up to date. - return ( - !this.isAuthenticated() && selectStatus(store.getState()) === "failed" - ); - } -} - -export default User; diff --git a/src/core/user.slice.js b/src/core/user.slice.js deleted file mode 100644 index f6649d3524..0000000000 --- a/src/core/user.slice.js +++ /dev/null @@ -1,44 +0,0 @@ -import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; - -// This thunk doesn't actually do anything but resolve straight away, -// but this allows us to chain a `.then()` on the action on the caller -// side. -export const attemptAuthentication = createAsyncThunk( - "user/attemptAuthentication", - () => Promise.resolve() -); - -const userSlice = createSlice({ - name: "user", - initialState: { status: "unauthenticated" }, - reducers: { - updateStatus(state, action) { - if (state.status === "unauthenticated" || state.status === "attempting") { - if (action.payload.hasToken) { - state.status = "authenticated"; - } else if (action.payload.doFail && state.status === "attempting") { - state.status = "failed"; - } - } - }, - setStatusAuthenticated(state) { - state.status = "authenticated"; - }, - setStatusUnauthenticated(state) { - state.status = "unauthenticated"; - } - }, - extraReducers: { - [attemptAuthentication.pending]: (state) => { - state.status = "attempting"; - } - } -}); - -export const { - updateStatus, - setStatusAuthenticated, - setStatusUnauthenticated -} = userSlice.actions; - -export default userSlice.reducer;