Skip to content

Commit f3a937a

Browse files
authored
TeamsProvider improvements and bug fixes (#132)
* published 0.1.0 * removed teams dependency and simplified teams sample * Setting up index for working with teams tabs * Fix for teams provider not closing the pop up when login in. Added loginhint to support single sign on * element providers now can depend on each other and only load when others are not available * minor cleanup * converted isAvailable from promise to regular getter * added comments and clean up - teams provider * applied workaround for acquireTokenSilent in TeamsProvider
1 parent f7aef81 commit f3a937a

File tree

11 files changed

+481
-232
lines changed

11 files changed

+481
-232
lines changed

auth.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<html>
2+
<head>
3+
<script src="https://unpkg.com/@microsoft/teams-js/dist/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
4+
<script type="module">
5+
import { TeamsProvider } from './dist/es6/providers/TeamsProvider.js';
6+
TeamsProvider.handleAuth();
7+
</script>
8+
</head>
9+
<body></body>
10+
</html>

index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,24 @@
99
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" rel="stylesheet" />
1010
<!-- <script src="./node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script> -->
1111

12+
<script src="https://unpkg.com/@microsoft/teams-js/dist/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
13+
1214
<!-- <script src="./dist/bundle/mgt-loader.js"></script> -->
1315

1416
<script type="module" src="dist/es6/index.js"></script>
1517
<script type="module" src="./dist/es6/mock/mgt-mock-provider.js"></script>
1618
</head>
1719

1820
<body>
21+
<mgt-teams-provider
22+
client-id="a974dfa0-9f57-49b9-95db-90f04ce2111a"
23+
auth-popup-url="auth.html"
24+
></mgt-teams-provider>
25+
1926
<mgt-msal-provider
2027
client-id="a974dfa0-9f57-49b9-95db-90f04ce2111a"
2128
scopes="user.read,people.read,user.readbasic.all,contacts.read,calendars.read"
29+
depends-on="mgt-teams-provider"
2230
></mgt-msal-provider>
2331

2432
<!-- <mgt-mock-provider></mgt-mock-provider> -->

src/Providers.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,9 @@
55
* -------------------------------------------------------------------------------------------
66
*/
77

8-
import { IProvider, EventDispatcher, EventHandler } from './providers/IProvider';
8+
import { EventDispatcher, EventHandler, IProvider } from './providers/IProvider';
99

1010
export class Providers {
11-
private static _eventDispatcher: EventDispatcher<ProvidersChangedState> = new EventDispatcher<
12-
ProvidersChangedState
13-
>();
14-
private static _globalProvider: IProvider;
15-
1611
public static get globalProvider(): IProvider {
1712
return this._globalProvider;
1813
}
@@ -39,6 +34,10 @@ export class Providers {
3934
public static removeProviderUpdatedListener(event: EventHandler<ProvidersChangedState>) {
4035
this._eventDispatcher.remove(event);
4136
}
37+
private static _eventDispatcher: EventDispatcher<ProvidersChangedState> = new EventDispatcher<
38+
ProvidersChangedState
39+
>();
40+
private static _globalProvider: IProvider;
4241

4342
private static handleProviderStateChanged() {
4443
Providers._eventDispatcher.fire(ProvidersChangedState.ProviderStateChanged);

src/components/providers/baseProvider.ts

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,61 @@
55
* -------------------------------------------------------------------------------------------
66
*/
77

8-
import { Providers } from '../../Providers';
8+
import { property } from 'lit-element';
9+
import { IProvider } from '../..';
910
import { MgtBaseComponent } from '../baseComponent';
1011

1112
export abstract class MgtBaseProvider extends MgtBaseComponent {
12-
constructor() {
13-
super();
14-
Providers.onProviderUpdated(() => this.loadState());
15-
this.loadState();
13+
public get provider() {
14+
return this._provider;
1615
}
1716

18-
private async loadState() {
19-
const provider = Providers.globalProvider;
17+
public set provider(value: IProvider) {
18+
if (this._provider) {
19+
this.provider.removeStateChangedHandler(() => this.stateChangedHandler);
20+
}
21+
this._provider = value;
22+
if (this._provider) {
23+
this.provider.onStateChanged(() => this.stateChangedHandler);
24+
}
25+
}
26+
27+
public abstract get isAvailable(): boolean;
2028

21-
if (provider) {
22-
provider.onStateChanged(() => {
23-
this.fireCustomEvent('onStateChanged', provider.state);
24-
});
29+
@property({
30+
attribute: 'depends-on',
31+
type: String,
32+
converter: newValue => {
33+
return document.querySelector(newValue);
2534
}
35+
})
36+
public dependsOn: MgtBaseProvider;
37+
38+
private _provider: IProvider;
39+
40+
protected firstUpdated(changedProperties) {
41+
super.firstUpdated(changedProperties);
42+
43+
let higherPriority = false;
44+
if (this.dependsOn) {
45+
let higherPriorityProvider = this.dependsOn;
46+
while (higherPriorityProvider) {
47+
if (higherPriorityProvider.isAvailable) {
48+
higherPriority = true;
49+
break;
50+
}
51+
higherPriorityProvider = higherPriorityProvider.dependsOn;
52+
}
53+
}
54+
55+
if (!higherPriority && this.isAvailable) {
56+
this.initializeProvider();
57+
}
58+
}
59+
60+
protected abstract initializeProvider();
61+
62+
private stateChangedHandler() {
63+
this.fireCustomEvent('onStateChanged', this.provider.state);
2664
}
2765
}

src/components/providers/mgt-msal-provider.ts

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,49 @@
55
* -------------------------------------------------------------------------------------------
66
*/
77

8-
import { LitElement, customElement, property } from 'lit-element';
9-
import { MsalConfig, MsalProvider } from '../../providers/MsalProvider';
10-
import { LoginType } from '../../providers/IProvider';
8+
import { customElement, LitElement, property } from 'lit-element';
119
import { Providers } from '../../Providers';
10+
import { LoginType } from '../../providers/IProvider';
11+
import { MsalConfig, MsalProvider } from '../../providers/MsalProvider';
12+
import { MgtBaseProvider } from './baseProvider';
1213

1314
@customElement('mgt-msal-provider')
14-
export class MgtMsalProvider extends LitElement {
15-
private _isInitialized: boolean = false;
16-
15+
export class MgtMsalProvider extends MgtBaseProvider {
1716
@property({
1817
type: String,
1918
attribute: 'client-id'
2019
})
21-
clientId = '';
20+
public clientId = '';
2221

2322
@property({
2423
type: String,
2524
attribute: 'login-type'
2625
})
27-
loginType;
26+
public loginType;
2827

29-
@property() authority;
28+
@property() public authority;
3029

3130
/* Comma separated list of scopes. */
3231
@property({
3332
type: String,
3433
attribute: 'scopes'
3534
})
36-
scopes;
35+
public scopes;
3736

38-
firstUpdated(changedProperties) {
39-
this.validateAuthProps();
37+
public get isAvailable() {
38+
return true;
4039
}
4140

42-
private validateAuthProps() {
43-
if (this._isInitialized) {
44-
return;
45-
}
46-
41+
protected initializeProvider() {
4742
if (this.clientId) {
48-
this._isInitialized = true;
49-
50-
let config: MsalConfig = {
43+
const config: MsalConfig = {
5144
clientId: this.clientId
5245
};
5346

5447
if (this.loginType && this.loginType.length > 1) {
5548
let loginType: string = this.loginType.toLowerCase();
5649
loginType = loginType[0].toUpperCase() + loginType.slice(1);
57-
let loginTypeEnum = LoginType[loginType];
50+
const loginTypeEnum = LoginType[loginType];
5851
config.loginType = loginTypeEnum;
5952
}
6053

@@ -63,13 +56,14 @@ export class MgtMsalProvider extends LitElement {
6356
}
6457

6558
if (this.scopes) {
66-
let scope = this.scopes.split(',');
59+
const scope = this.scopes.split(',');
6760
if (scope && scope.length > 0) {
6861
config.scopes = scope;
6962
}
7063
}
7164

72-
Providers.globalProvider = new MsalProvider(config);
65+
this.provider = new MsalProvider(config);
66+
Providers.globalProvider = this.provider;
7367
}
7468
}
7569
}

src/components/providers/mgt-teams-provider.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,52 @@
55
* -------------------------------------------------------------------------------------------
66
*/
77

8-
import { LitElement, customElement, property } from 'lit-element';
8+
import { customElement, LitElement, property } from 'lit-element';
99
import { Providers } from '../../Providers';
10-
import { TeamsProvider } from '../../providers/TeamsProvider';
10+
import { TeamsConfig, TeamsProvider } from '../../providers/TeamsProvider';
11+
import { MgtBaseProvider } from './baseProvider';
1112

1213
@customElement('mgt-teams-provider')
13-
export class MgtTeamsProvider extends LitElement {
14-
private _provider: TeamsProvider;
15-
14+
export class MgtTeamsProvider extends MgtBaseProvider {
1615
@property({
1716
type: String,
1817
attribute: 'client-id'
1918
})
20-
clientId = '';
19+
public clientId = '';
2120

2221
@property({
2322
type: String,
2423
attribute: 'auth-popup-url'
2524
})
26-
authPopupUrl = '';
25+
public authPopupUrl = '';
2726

28-
async firstUpdated(changedProperties) {
29-
this.validateAuthProps();
30-
if (await TeamsProvider.isAvailable()) {
31-
Providers.globalProvider = this._provider;
32-
}
27+
/* Comma separated list of scopes. */
28+
@property({
29+
type: String,
30+
attribute: 'scopes'
31+
})
32+
public scopes;
33+
34+
public get isAvailable() {
35+
return TeamsProvider.isAvailable;
3336
}
3437

35-
private validateAuthProps() {
38+
protected initializeProvider() {
3639
if (this.clientId && this.authPopupUrl) {
37-
if (!this._provider) {
38-
this._provider = new TeamsProvider({
39-
clientId: this.clientId,
40-
authPopupUrl: this.authPopupUrl
41-
});
40+
const config: TeamsConfig = {
41+
authPopupUrl: this.authPopupUrl,
42+
clientId: this.clientId
43+
};
44+
45+
if (this.scopes) {
46+
const scope = this.scopes.split(',');
47+
if (scope && scope.length > 0) {
48+
config.scopes = scope;
49+
}
4250
}
51+
52+
this.provider = new TeamsProvider(config);
53+
Providers.globalProvider = this.provider;
4354
}
4455
}
4556
}

src/mock/mgt-mock-provider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
* -------------------------------------------------------------------------------------------
66
*/
77

8-
import { LitElement, customElement } from 'lit-element';
9-
import { MockProvider } from './MockProvider';
8+
import { customElement, LitElement } from 'lit-element';
109
import { Providers } from '../Providers';
10+
import { MockProvider } from './MockProvider';
1111

1212
@customElement('mgt-mock-provider')
1313
export class MgtMockProvider extends LitElement {

src/providers/IProvider.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,57 +13,57 @@ export abstract class IProvider implements AuthenticationProvider {
1313
private _state: ProviderState;
1414
private _loginChangedDispatcher = new EventDispatcher<LoginChangedEvent>();
1515

16-
get state(): ProviderState {
16+
public get state(): ProviderState {
1717
return this._state;
1818
}
1919

20-
setState(state: ProviderState) {
21-
if (state != this._state) {
20+
public setState(state: ProviderState) {
21+
if (state !== this._state) {
2222
this._state = state;
2323
this._loginChangedDispatcher.fire({});
2424
}
2525
}
2626

2727
// events
28-
onStateChanged(eventHandler: EventHandler<LoginChangedEvent>) {
28+
public onStateChanged(eventHandler: EventHandler<LoginChangedEvent>) {
2929
this._loginChangedDispatcher.add(eventHandler);
3030
}
3131

32-
removeStateChangedHandler(eventHandler: EventHandler<LoginChangedEvent>) {
32+
public removeStateChangedHandler(eventHandler: EventHandler<LoginChangedEvent>) {
3333
this._loginChangedDispatcher.remove(eventHandler);
3434
}
3535

3636
constructor() {
3737
this._state = ProviderState.Loading;
3838
}
3939

40-
login?(): Promise<void>;
41-
logout?(): Promise<void>;
42-
getAccessTokenForScopes(...scopes: string[]): Promise<string> {
43-
return this.getAccessToken({ scopes: scopes });
40+
public login?(): Promise<void>;
41+
public logout?(): Promise<void>;
42+
public getAccessTokenForScopes(...scopes: string[]): Promise<string> {
43+
return this.getAccessToken({ scopes });
4444
}
4545

46-
abstract getAccessToken(options?: AuthenticationProviderOptions): Promise<string>;
47-
graph: Graph;
46+
public abstract getAccessToken(options?: AuthenticationProviderOptions): Promise<string>;
47+
public graph: Graph;
4848
}
4949

5050
export type EventHandler<E> = (event: E) => void;
5151
export interface LoginChangedEvent {}
5252

5353
export class EventDispatcher<E> {
54-
private eventHandlers: EventHandler<E>[] = [];
54+
private eventHandlers: Array<EventHandler<E>> = [];
5555

56-
fire(event: E) {
57-
for (let handler of this.eventHandlers) {
56+
public fire(event: E) {
57+
for (const handler of this.eventHandlers) {
5858
handler(event);
5959
}
6060
}
6161

62-
add(eventHandler: EventHandler<E>) {
62+
public add(eventHandler: EventHandler<E>) {
6363
this.eventHandlers.push(eventHandler);
6464
}
6565

66-
remove(eventHandler: EventHandler<E>) {
66+
public remove(eventHandler: EventHandler<E>) {
6767
for (let i = 0; i < this.eventHandlers.length; i++) {
6868
if (this.eventHandlers[i] === eventHandler) {
6969
this.eventHandlers.splice(i, 1);

0 commit comments

Comments
 (0)