зеркало из
1
0
Форкнуть 0
opensource-management-portal/routes/settings/personalAccessTokens.ts

145 строки
4.5 KiB
TypeScript
Исходник Обычный вид История

2018-05-02 20:40:50 +03:00
//
// Copyright (c) Microsoft.
2018-05-02 20:40:50 +03:00
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, getProviders } from '../../transitional';
import { PersonalAccessToken } from '../../entities/token/token';
interface IPersonalAccessTokenForDisplay {
active: boolean;
expired: boolean;
expires: string;
identifier: string;
description: string;
apis: string[];
tokenEntity: PersonalAccessToken;
}
export interface IRequestForSettingsPersonalAccessTokens extends ReposAppRequest {
personalAccessTokens?: IPersonalAccessTokenForDisplay[];
}
2018-05-02 20:40:50 +03:00
const serviceName = 'repos-pat';
const tokenExpirationMs = 1000 * 60 * 60 * 24 * 365; // 365 days
function translateTableToEntities(personalAccessTokens: PersonalAccessToken[]): IPersonalAccessTokenForDisplay[] {
return personalAccessTokens.map(pat => {
// So that we do not share the hashed key with the user, we
// build a hash of that and the timestamp to offer a single-version
// tag to use for delete operations, etc.
const displayToken: IPersonalAccessTokenForDisplay = {
active: pat.active,
expired: pat.isExpired(),
expires: pat.expires ? pat.expires.toDateString() : null,
description: pat.description,
apis: pat.scopes ? pat.scopes.split(',') : [],
identifier: pat.getIdentifier(),
tokenEntity: pat,
};
return displayToken;
});
2018-05-02 20:40:50 +03:00
}
function getPersonalAccessTokens(req: ReposAppRequest, res, next) {
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
const corporateId = req.individualContext.corporateIdentity.id;
tokenProvider.queryTokensForCorporateId(corporateId).then(tokens => {
req['personalAccessTokens'] = translateTableToEntities(tokens);
2018-05-02 20:40:50 +03:00
return next();
}).catch(error => {
return next(error);
2018-05-02 20:40:50 +03:00
});
}
function view(req: IRequestForSettingsPersonalAccessTokens, res) {
2018-05-02 20:40:50 +03:00
const personalAccessTokens = req.personalAccessTokens;
req.individualContext.webContext.render({
view: 'settings/personalAccessTokens',
title: 'Personal access tokens',
state: {
personalAccessTokens,
newKey: res.newKey,
isPreviewUser: true, //req.isPreviewUser,
},
2018-05-02 20:40:50 +03:00
});
}
router.use(getPersonalAccessTokens);
router.get('/', view);
function createToken(req: ReposAppRequest, res, next) {
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
2018-05-02 20:40:50 +03:00
const insights = req.insights;
const description = req.body.description;
if (!description) {
return next(new Error('A description is required to create a new Personal Access Token'));
}
const corporateId = req.individualContext.corporateIdentity.id;
const token = PersonalAccessToken.CreateNewToken();
token.corporateId = corporateId;
token.description = description;
2018-05-02 20:40:50 +03:00
const now = new Date();
token.expires = new Date(now.getTime() + tokenExpirationMs);
token.source = serviceName;
token.scopes = 'extension,links';
2018-05-02 20:40:50 +03:00
insights.trackEvent({
name: 'ReposCreateTokenStart',
properties: {
id: corporateId,
2018-05-02 20:40:50 +03:00
description: description,
},
});
tokenProvider.saveNewToken(token).then(ok => {
insights.trackEvent({
name: 'ReposCreateTokenFinish',
properties: {
id: corporateId,
description: description,
},
});
const newKey = token.getPrivateKey();
2018-05-02 20:40:50 +03:00
getPersonalAccessTokens(req, res, () => {
res.newKey = newKey;
return view(req, res);
2018-05-02 20:40:50 +03:00
});
}).catch(insertError => {
insights.trackEvent({
name: 'ReposCreateTokenFailure',
properties: {
id: corporateId,
description: description,
},
2018-05-02 20:40:50 +03:00
});
return next(insertError);
2018-05-02 20:40:50 +03:00
});
}
router.post('/create', createToken);
router.post('/extension', createToken);
2018-05-02 20:40:50 +03:00
router.post('/delete', asyncHandler(async (req: IRequestForSettingsPersonalAccessTokens, res, next) => {
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
2018-05-02 20:40:50 +03:00
const revokeAll = req.body.revokeAll === '1';
const revokeIdentifier = req.body.revoke;
const personalAccessTokens = req.personalAccessTokens;
for (const pat of personalAccessTokens) {
const token = pat.tokenEntity;
2018-05-02 20:40:50 +03:00
if (revokeAll || pat.identifier === revokeIdentifier) {
token.active = false;
await tokenProvider.updateToken(token);
2018-05-02 20:40:50 +03:00
}
}
return res.redirect('/settings/security/tokens');
}));
2018-05-02 20:40:50 +03:00
export default router;