-
Notifications
You must be signed in to change notification settings - Fork 0
/
require-token-login.ts
110 lines (93 loc) · 2.82 KB
/
require-token-login.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import {htm} from '@zeit/integration-utils';
import Integration from './integration';
export interface Token {
key: string;
name: string;
}
export interface RequireTokenOptions {
projectScoped?: boolean,
tokens?: Token[],
testTokens?: (tokens: {[key: string]: string}) => Promise<string | false> | string | false;
LoginView?: (props: LoginViewProps) => any
}
export interface LoginViewProps {
error?: string,
message?: string,
tokens?: (Token & {value: string})[]
}
export const DefaultLoginView = ({
error = '',
message = '',
tokens = []
}: LoginViewProps) => htm`
<Page>
<Box>${message}</Box>
<Fieldset>
<FsContent>
<FsSubtitle>Please enter the following information</FsSubtitle>
${
tokens.map(token => htm`
<Input label=${token.name} name=${token.key} width="100%" value=${token.value || ''} />
`)
}
</FsContent>
<FsFooter>
<Box width="100%" display="flex" justifyContent="space-between">
<Box>${error}</Box>
<Button small action="setToken">Connect</Button>
</Box>
</FsFooter>
</Fieldset>
</Page>
`;
export const requireTokenLogin = ({
projectScoped = false,
tokens = [],
testTokens = () => false,
LoginView = DefaultLoginView
}: RequireTokenOptions = {}) => (app: Integration) => {
if (tokens.length === 0) {
tokens.push({
key: 'token',
name: 'API Token',
});
}
app.use('setToken', async ({utils}, next) => {
const tokensWithValues = tokens.map(token => ({...token, value: utils.get(token.key)}));
if (tokensWithValues.some(token => !token.value)) {
return htm`<${LoginView} error="All fields are required" tokens=${tokensWithValues}/>`
}
const error = await testTokens(tokensWithValues.reduce((acc, token) => ({...acc, [token.key]: token.value}), {}));
if (error) {
return htm`<${LoginView} error=${error} tokens=${tokensWithValues}/>`;
}
for (const token of tokensWithValues) {
if (projectScoped && utils.projectStore) {
utils.projectStore[token.key] = token.value;
} else {
utils.store[token.key] = token.value;
}
}
await utils.saveStore();
next();
});
app.use('logout', async ({utils}) => {
for (const token of tokens) {
if (projectScoped && utils.projectStore) {
delete utils.projectStore[token.key];
} else {
delete utils.store[token.key];
}
}
await utils.saveStore();
return htm`<${LoginView} message="You have logged out successfully"/>`;
});
app.use(async ({utils}, next) => {
const tokenStore = projectScoped ? utils.projectStore : utils.store;
if (tokenStore && tokens.every(token => Boolean(tokenStore[token.key]))) {
next();
} else {
return htm`<${LoginView} tokens=${tokens}/>`;
}
});
};