Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 into 2806
  • Loading branch information
tdurnford committed Feb 10, 2020
2 parents 3d7d9ee + 11aa92d commit b520de3
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.button-container {
display: flex;
flex: 1;
position: relative;
}

.card {
font-family: inherit;
padding: 10px;
}

.card > .buttons {
align-items: stretch;
display: flex;
flex-direction: column;
}

.card > .buttons > .button-container > button {
flex: 1;
color: #0063B1;
background-color: white;
border-style: solid;
border-width: 1px;
font-weight: 600;
padding: 10px
}

.card > .buttons > .button-container:last-of-type {
margin-top: 8px;
}

.container {
width: 10px;
text-align: center;
}

.status {
position: absolute;
top: 9px;
right: 9px;
}

.separator {
height: 8px;
}

/*
Your use of the content in the files referenced here is subject to the terms of the license at https://aka.ms/fabric-assets-license
*/
@font-face {
font-family: 'FabricMDL2Icons';
src: url('data:application/octet-stream;base64,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') format('truetype');
}

.ms-Icon {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-family: 'FabricMDL2Icons';
font-style: normal;
font-weight: normal;
speak: none;
}

.ms-Icon--SkypeCircleCheck:before {
color: green;
content: "\EF7D";
font-size: 16px;
padding-top: 4;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { useCallback, useContext, useEffect, useMemo, useState, useRef } from 'react';
import { hooks } from 'botframework-webchat';
import { Spinner } from 'office-ui-fabric-react/lib/Spinner';

import './index.css';
import OAuthContext from '../../../../oauth/Context';

const { useActivities, usePostActivity } = hooks;

const AUTHENTICATING = 'AUTHENTICATING';
const AUTHENTICATION_FAILED = 'AUTHENTICATION_FAILED';
const AUTHENTICATION_PENDING = 'AUTHENTICATION_PENDING';
const AUTHENTICATION_SUCCESSFUL = 'AUTHENTICATION_SUCCESSFUL';

const OnBehalfOfAttachment = ({ card, next }) => {
const {
attachment: {
content: { connectionName, tokenExchangeResource: { id, uri } = {} }
}
} = card;
const { acquireToken, getAccount } = useContext(OAuthContext);
const [authenticationStatus, setAuthenticationStatus] = useState(AUTHENTICATION_PENDING);
const { current: invokeId } = useRef(
Math.random()
.toString(36)
.substr(2, 10)
);
const oauthCard = useMemo(() => next(card), [next, card]);

const [activities] = useActivities();
const postActivity = usePostActivity();

const exchangeToken = useCallback(
async resourceUri => {
const user = getAccount();
if (user) {
const { accessToken } = await acquireToken({ scopes: [resourceUri] });
return accessToken;
}
setAuthenticationStatus(AUTHENTICATION_FAILED);
},
[acquireToken, getAccount]
);

useEffect(() => {
const invokeActivity = activities.find(
({ channelData: { invokeId: activityInvokeId } = {} }) => invokeId === activityInvokeId
);
if (invokeActivity) {
const { channelData: { state } = {} } = invokeActivity;
if (state === 'send failed') {
setAuthenticationStatus(AUTHENTICATION_FAILED);
} else if (state === 'sent') {
setAuthenticationStatus(AUTHENTICATION_SUCCESSFUL);
}
}
}, [activities, invokeId]);

useEffect(() => {
if (authenticationStatus === AUTHENTICATING) {
(async function() {
try {
const token = await exchangeToken('api://61598522-abf1-49ba-bbb4-3fb89f4ad9a6/ReadUser');
token &&
postActivity({
channelData: { invokeId },
type: 'invoke',
name: 'signin/tokenExchange',
value: {
id,
connectionName,
token
}
});
} catch (error) {
setAuthenticationStatus(AUTHENTICATION_FAILED);
}
})();
}
}, [authenticationStatus]);

const handleClickAllow = useCallback(() => {
authenticationStatus !== AUTHENTICATING && setAuthenticationStatus(AUTHENTICATING);
}, [authenticationStatus, setAuthenticationStatus]);

if (authenticationStatus === AUTHENTICATION_FAILED) {
return oauthCard;
}

return (
<div className="card">
<div>The Bot has requested to access your account</div>
<div className="separator" />
<div className="ac-actionSet buttons">
<div className="button-container">
<button className="ac-pushButton style-default" type="button" onClick={handleClickAllow}>
Allow
</button>
<div className="status">
{authenticationStatus === AUTHENTICATING ? (
<Spinner />
) : authenticationStatus === AUTHENTICATION_SUCCESSFUL ? (
<i className="ms-Icon ms-Icon--SkypeCircleCheck" aria-hidden="true" />
) : null}
</div>
</div>
</div>
</div>
);
};

export default OnBehalfOfAttachment;

0 comments on commit b520de3

Please sign in to comment.