Skip to content

Commit 9af2bf5

Browse files
sebastienlevertmusalegavinbarron
authored
feat: Storybook authentication (#2048)
* Support for Storybook auth with MGT * Styling * Support for params + custom client * Relying on blank.html vs. storybook for auth * Adding ref to blank * Adding the auth page as env * Updates to use central App ID * Fixing auth within stories * Back with theming + deleted signInAddon * updating client_id to use torus app --------- Co-authored-by: Musale Martin <[email protected]> Co-authored-by: Gavin Barron <[email protected]>
1 parent a24fd25 commit 9af2bf5

File tree

8 files changed

+165
-142
lines changed

8 files changed

+165
-142
lines changed

.storybook/addons/codeEditorAddon/codeAddon.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import { makeDecorator } from '@storybook/addons';
1+
import addons, { makeDecorator } from '@storybook/addons';
2+
3+
import { ProviderState } from '../../../packages/mgt-element/dist/es6/providers/IProvider';
24
import { EditorElement } from './editor';
5+
import { CLIENTID, SETPROVIDER_EVENT, AUTH_PAGE } from '../../env';
36

47
const mgtScriptName = './mgt.storybook.js';
58

@@ -154,6 +157,7 @@ export const withCodeEditor = makeDecorator({
154157
}
155158
}
156159
}
160+
157161
const themeToggleCss = disableThemeToggle
158162
? ''
159163
: `
@@ -177,12 +181,33 @@ export const withCodeEditor = makeDecorator({
177181
<mgt-theme-toggle mode="light"></mgt-theme-toggle>
178182
</header>
179183
`;
180-
const loadEditorContent = () => {
181-
let providerInitCode = `
182-
import {Providers, MockProvider} from "${mgtScriptName}";
183-
Providers.globalProvider = new MockProvider(true);
184-
`;
185184

185+
let providerInitCode = `
186+
import {Providers, MockProvider} from "${mgtScriptName}";
187+
Providers.globalProvider = new MockProvider(true);
188+
`;
189+
190+
const channel = addons.getChannel();
191+
channel.on(SETPROVIDER_EVENT, params => {
192+
if (params.state === ProviderState.SignedIn && params.name === 'MgtMockProvider') {
193+
providerInitCode = `
194+
import { Providers, MockProvider } from "${mgtScriptName}";
195+
Providers.globalProvider = new MockProvider(true);
196+
`;
197+
} else if (params.state === ProviderState.SignedIn && params.name === 'MgtMsal2Provider') {
198+
providerInitCode = `
199+
import { Providers, Msal2Provider, LoginType } from "${mgtScriptName}";
200+
Providers.globalProvider = new Msal2Provider({
201+
clientId: "${CLIENTID}",
202+
loginType: LoginType.Popup,
203+
redirectUri: "${window.location.origin}/${AUTH_PAGE}"
204+
});`;
205+
}
206+
207+
loadEditorContent();
208+
});
209+
210+
const loadEditorContent = () => {
186211
const storyElement = document.createElement('iframe');
187212

188213
storyElement.addEventListener(
@@ -201,8 +226,7 @@ export const withCodeEditor = makeDecorator({
201226
<head>
202227
<script type="module" src="${mgtScriptName}"></script>
203228
<script type="module">
204-
import {Providers, MockProvider} from "${mgtScriptName}";
205-
Providers.globalProvider = new MockProvider(true);
229+
${providerInitCode}
206230
</script>
207231
<style>
208232
html, body {

.storybook/addons/signInAddon/signInAddon.js

Lines changed: 0 additions & 41 deletions
This file was deleted.

.storybook/env.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
export const CLIENTID = 'ac77046c-156c-40f0-8507-3b5a58034582';
1+
export const CLIENTID = '9aeac104-a6b6-45ca-bb7c-bf7c3083eeb2';
22
export const GETPROVIDER_EVENT = 'mgt/getProvider';
33
export const SETPROVIDER_EVENT = 'mgt/setProvider';
4+
export const AUTH_PAGE = 'blank.html';

.storybook/manager-head.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@
1111
<a tabindex="-1" href="https://privacy.microsoft.com/en-us/privacystatement">Privacy & cookies</a>
1212
<a tabindex="-1" href="https://www.microsoft.com/en-us/legal/intellectualproperty/copyright/default">Term of use</a>
1313
</footer>
14-
<script type="module">
15-
import { PACKAGE_VERSION } from './mgt.storybook.js'
16-
document.getElementById('mgt-version').innerText = PACKAGE_VERSION;
17-
</script>
1814

1915
<script src="https://consentdeliveryfd.azurefd.net/mscc/lib/v2/wcp-consent.js"></script>
2016
<script src="https://az725175.vo.msecnd.net/scripts/jsll-4.js" type="text/javascript"></script>
17+
<script type="module" src="https://unpkg.com/@fluentui/web-components@2"></script>
2118
<script type="text/javascript">
2219
const xmlns = "http://www.w3.org/2000/svg";
2320

.storybook/manager.js

Lines changed: 111 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,88 +6,126 @@
66
*/
77

88
import { addons, types } from '@storybook/addons';
9-
import { STORIES_CONFIGURED, STORY_MISSING } from '@storybook/core-events';
10-
119
import theme from './theme';
1210

13-
// import React, { useState } from 'react';
14-
// import { AddonPanel } from '@storybook/components';
15-
// import { useParameter, useChannel } from '@storybook/api';
16-
// import { Providers, LoginType, MsalProvider } from '../packages/mgt/dist/es6';
17-
// import { CLIENTID, GETPROVIDER_EVENT, SETPROVIDER_EVENT } from './env';
18-
19-
// const PARAM_KEY = 'signInAddon';
20-
// const _allow_signin = false;
21-
22-
// const msalProvider = new MsalProvider({
23-
// clientId: CLIENTID,
24-
// loginType: LoginType.Popup
25-
// });
26-
27-
// Providers.globalProvider = msalProvider;
28-
29-
// const SignInPanel = () => {
30-
// const value = useParameter(PARAM_KEY, null);
31-
32-
// const [state, setState] = useState(Providers.globalProvider.state);
33-
34-
// const emit = useChannel({
35-
// STORY_RENDERED: id => {
36-
// console.log('storyRendered', id);
37-
// },
38-
// [GETPROVIDER_EVENT]: params => {
39-
// emitProvider(state);
40-
// }
41-
// });
42-
43-
// const emitProvider = loginState => {
44-
// emit(SETPROVIDER_EVENT, { state: loginState });
45-
// };
46-
47-
// Providers.onProviderUpdated(() => {
48-
// setState(Providers.globalProvider.state);
49-
// emitProvider(Providers.globalProvider.state);
50-
// });
51-
52-
// emitProvider(state);
53-
54-
// return (
55-
// <div>
56-
// {_allow_signin ? (
57-
// <mgt-login />
58-
// ) : (
59-
// 'All components are using mock data - sign in function will be available in a future release'
60-
// )}
61-
// </div>
62-
// );
63-
// };
11+
import React, { useState } from 'react';
12+
import { useChannel } from '@storybook/api';
13+
import { Providers } from '../packages/mgt-element/dist/es6/providers/Providers';
14+
import { ProviderState, LoginType } from '../packages/mgt-element/dist/es6/providers/IProvider';
15+
import { Msal2Provider } from '../packages/providers/mgt-msal2-provider/dist/es6/Msal2Provider';
16+
import { CLIENTID, SETPROVIDER_EVENT, AUTH_PAGE } from './env';
17+
import { MockProvider } from '@microsoft/mgt-element';
18+
import { PACKAGE_VERSION } from '../packages/mgt-element/dist/es6/utils/version';
19+
import '../packages/mgt-components/dist/es6/components/mgt-login/mgt-login';
20+
import '../packages/mgt-components/dist/es6/components/mgt-person/mgt-person';
21+
22+
const isLoginEnabled = () => {
23+
const urlParams = new window.URL(window.location.href).searchParams;
24+
const canLogin = urlParams.get('login');
25+
26+
return canLogin === 'true';
27+
};
28+
29+
const getClientId = () => {
30+
const urlParams = new window.URL(window.location.href).searchParams;
31+
const customClientId = urlParams.get('clientId');
32+
33+
return isLoginEnabled() && customClientId ? customClientId : CLIENTID;
34+
};
35+
36+
document.getElementById('mgt-version').innerText = PACKAGE_VERSION;
37+
38+
const mockProvider = new MockProvider(true);
39+
const msal2Provider = new Msal2Provider({
40+
clientId: getClientId(),
41+
redirectUri: window.location.origin + '/' + AUTH_PAGE,
42+
scopes: [
43+
// capitalize all words in the scope
44+
'user.read',
45+
'user.read.all',
46+
'mail.readBasic',
47+
'people.read',
48+
'people.read.all',
49+
'sites.read.all',
50+
'user.readbasic.all',
51+
'contacts.read',
52+
'presence.read',
53+
'presence.read.all',
54+
'tasks.readwrite',
55+
'tasks.read',
56+
'calendars.read',
57+
'group.read.all',
58+
'files.read',
59+
'files.read.all',
60+
'files.readwrite',
61+
'files.readwrite.all'
62+
],
63+
loginType: LoginType.Popup
64+
});
65+
66+
Providers.globalProvider = msal2Provider;
67+
68+
const SignInPanel = () => {
69+
const [state, setState] = useState(Providers.globalProvider.state);
70+
const [loginEnabled] = useState(isLoginEnabled());
71+
72+
const emit = useChannel({
73+
STORY_RENDERED: id => {
74+
console.log('storyRendered', id);
75+
}
76+
});
77+
78+
const emitProvider = loginState => {
79+
if (Providers.globalProvider.state === ProviderState.SignedOut && Providers.globalProvider !== mockProvider) {
80+
emit(SETPROVIDER_EVENT, { state: loginState, provider: mockProvider, name: 'MgtMockProvider' });
81+
} else {
82+
emit(SETPROVIDER_EVENT, { state: loginState, provider: msal2Provider, name: 'MgtMsal2Provider' });
83+
}
84+
};
85+
86+
Providers.onProviderUpdated(() => {
87+
setState(Providers.globalProvider.state);
88+
emitProvider(Providers.globalProvider.state);
89+
});
90+
91+
const onSignOut = () => {
92+
Providers.globalProvider.logout();
93+
};
94+
95+
emitProvider(state);
96+
97+
return (
98+
<>
99+
{loginEnabled && (
100+
<>
101+
{Providers.globalProvider.state !== ProviderState.SignedIn ? (
102+
<mgt-login login-view="compact" style={{ marginTop: '3px' }}></mgt-login>
103+
) : (
104+
<>
105+
<mgt-person person-query="me" style={{ marginTop: '8px' }}></mgt-person>
106+
<fluent-button appearance="lightweight" style={{ marginTop: '3px' }} onClick={onSignOut}>
107+
Sign Out
108+
</fluent-button>
109+
</>
110+
)}
111+
</>
112+
)}
113+
</>
114+
);
115+
};
64116

65117
addons.setConfig({
66118
enableShortcuts: false,
67119
theme
68120
});
69121

70122
addons.register('microsoft/graph-toolkit', storybookAPI => {
71-
storybookAPI.on(STORIES_CONFIGURED, (kind, story) => {
72-
if (storybookAPI.getUrlState().path === '/story/*') {
73-
storybookAPI.selectStory('mgt-login', 'login');
74-
}
75-
});
123+
const render = ({ active }) => <SignInPanel />;
76124

77-
storybookAPI.on(STORY_MISSING, (kind, story) => {
78-
storybookAPI.selectStory('mgt-login', 'login');
125+
addons.add('mgt/sign-in', {
126+
type: types.TOOLEXTRA,
127+
title: 'Sign In',
128+
match: ({ viewMode }) => true,
129+
render
79130
});
80-
81-
// const render = ({ active, key }) => (
82-
// <AddonPanel active={active} key={key}>
83-
// <SignInPanel />
84-
// </AddonPanel>
85-
// );
86-
87-
// addons.add('mgt/sign-in', {
88-
// type: types.PANEL,
89-
// title: 'Sign In',
90-
// render,
91-
// paramKey: PARAM_KEY
92-
// });
93131
});

.vscode/extensions.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"bierner.lit-html",
77
"esbenp.prettier-vscode",
88
"rebornix.project-snippets",
9-
"ms-vscode.vscode-typescript-tslint-plugin",
10-
"msjsdiag.debugger-for-edge"
9+
"ms-vscode.vscode-typescript-tslint-plugin"
1110
]
1211
}

assets/blank.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<html>
2+
<head>
3+
<script src="https://unpkg.com/@microsoft/mgt@2/dist/bundle/mgt-loader.js"></script>
4+
<mgt-msal2-provider client-id="6b5a42f1-9e1a-4a20-9df2-9b058df3c213"></mgt-msal2-provider>
5+
</head>
6+
<body></body>
7+
</html>

assets/sw.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ if (!self.define) {
44
const n = (n, e) => (
55
(n = new URL(n + '.js', e).href),
66
i[n] ||
7-
new Promise(i => {
8-
if ('document' in self) {
9-
const c = document.createElement('script');
10-
(c.src = n), (c.onload = i), document.head.appendChild(c);
11-
} else (c = n), importScripts(n), i();
12-
}).then(() => {
13-
let c = i[n];
14-
if (!c) throw new Error(`Module ${n} didn’t register its module`);
15-
return c;
16-
})
7+
new Promise(i => {
8+
if ('document' in self) {
9+
const c = document.createElement('script');
10+
(c.src = n), (c.onload = i), document.head.appendChild(c);
11+
} else (c = n), importScripts(n), i();
12+
}).then(() => {
13+
let c = i[n];
14+
if (!c) throw new Error(`Module ${n} didn’t register its module`);
15+
return c;
16+
})
1717
);
1818
self.define = (e, o) => {
1919
const f = c || ('document' in self ? document.currentScript.src : '') || location.href;
@@ -32,7 +32,6 @@ define(['./workbox-dae083bf'], function (c) {
3232
c.precacheAndRoute(
3333
[
3434
{ url: 'favicon.png', revision: '1bc73a93f5aa3c02fe25899cf0a2e10d' },
35-
{ url: 'github.png', revision: 'a2f37fc5d3cdf6e15dd31e5a16050b93' },
3635
{ url: 'graff.png', revision: '374e94d8e3aed9fa88a9923e5eaacea2' },
3736
{ url: 'icons/100x100-icon.png', revision: 'fba112b56be61bcb1ade15c2f96fe129' },
3837
{ url: 'icons/1024x1024-icon.png', revision: 'b1cfd1dd029d2fbde88ff06c573dc290' },
@@ -98,8 +97,7 @@ define(['./workbox-dae083bf'], function (c) {
9897
{ url: 'icons/96x96-icon.png', revision: '521fb6b0d2e5e477b71c5dac1b022b9c' },
9998
{ url: 'manifest.json', revision: 'ee016e1fe5c51f6cca2a570d121c33b8' },
10099
{ url: 'mgt.png', revision: '0a1f53f06c9711cf7d83128cd76e7f8e' },
101-
{ url: 'mgt.storybook.js', revision: 'bebf2959d77ab8a92a7afa4f4780472a' },
102-
{ url: 'npm.png', revision: '2f06f214d1f56e962303c702f8186d6f' }
100+
{ url: 'mgt.storybook.js', revision: 'bebf2959d77ab8a92a7afa4f4780472a' }
103101
],
104102
{ ignoreURLParametersMatching: [/^utm_/, /^fbclid$/] }
105103
);

0 commit comments

Comments
 (0)