API session refactor + directory prune
- Client APIs remain behind the session middleware - Non-client APIs no longer set cookies given their stateless nature - Simplifies the directory structure - Removes Microsoft-specific API configuration and code not useful to the OSS version
This commit is contained in:
Родитель
a654aa7117
Коммит
66b87b31d0
20
.cspell.json
20
.cspell.json
|
@ -30,6 +30,7 @@
|
|||
"aadupn",
|
||||
"accountinfo",
|
||||
"accountinformation",
|
||||
"actionperms",
|
||||
"actionschecked",
|
||||
"actionsconfigured",
|
||||
"actionscreated",
|
||||
|
@ -170,8 +171,8 @@
|
|||
"datasharing",
|
||||
"datatable",
|
||||
"DATETIME",
|
||||
"dcount",
|
||||
"dbaeumer",
|
||||
"dcount",
|
||||
"decisionmaker",
|
||||
"Decisionmaker",
|
||||
"Decisionmakers",
|
||||
|
@ -179,8 +180,8 @@
|
|||
"defaultbranch",
|
||||
"deferreason",
|
||||
"deislabs",
|
||||
"deletesettingsorgname",
|
||||
"deletedetected",
|
||||
"deletesettingsorgname",
|
||||
"demilestoned",
|
||||
"departedowners",
|
||||
"deployr",
|
||||
|
@ -278,6 +279,7 @@
|
|||
"GHID",
|
||||
"ghname",
|
||||
"ghowners",
|
||||
"ghossapis",
|
||||
"GHPI",
|
||||
"ghpimigrationphase",
|
||||
"ghrp",
|
||||
|
@ -319,6 +321,7 @@
|
|||
"IAAD",
|
||||
"ictext",
|
||||
"identicons",
|
||||
"idtoken",
|
||||
"iitemp",
|
||||
"inclusivity",
|
||||
"indiv",
|
||||
|
@ -354,6 +357,7 @@
|
|||
"jeffwilcox",
|
||||
"jitgrants",
|
||||
"joblog",
|
||||
"jobname",
|
||||
"jsoncontribution",
|
||||
"jsoncreated",
|
||||
"jwilcox",
|
||||
|
@ -402,6 +406,7 @@
|
|||
"Maintainerships",
|
||||
"maintainerupdated",
|
||||
"maintainerupdatedby",
|
||||
"maintainerupdatedbytext",
|
||||
"maints",
|
||||
"maluuba",
|
||||
"Maluuba",
|
||||
|
@ -561,6 +566,8 @@
|
|||
"Passcode",
|
||||
"patachable",
|
||||
"pcontent",
|
||||
"permlevel",
|
||||
"permscheckdate",
|
||||
"petyan",
|
||||
"pglink",
|
||||
"pgpool",
|
||||
|
@ -595,6 +602,7 @@
|
|||
"Puid",
|
||||
"pullmerges",
|
||||
"pullrequestreview",
|
||||
"pullrequests",
|
||||
"pullrequestsmerged",
|
||||
"pullrequestsopened",
|
||||
"pushd",
|
||||
|
@ -637,6 +645,7 @@
|
|||
"repositorymetadata",
|
||||
"repositoryname",
|
||||
"repositoryprivate",
|
||||
"repositoryprojects",
|
||||
"repositoryteamcache",
|
||||
"reposize",
|
||||
"requestedtime",
|
||||
|
@ -659,10 +668,11 @@
|
|||
"samplevault",
|
||||
"Satya",
|
||||
"scansummary",
|
||||
"scorecardreprocessrequest",
|
||||
"SCIM",
|
||||
"scorecardreprocessrequest",
|
||||
"secretscanningonpush",
|
||||
"secscandata",
|
||||
"securityevents",
|
||||
"securitygroupalias",
|
||||
"selfid",
|
||||
"SELFSERVICE",
|
||||
|
@ -755,13 +765,13 @@
|
|||
"tlink",
|
||||
"tolower",
|
||||
"totalcount",
|
||||
"toupper",
|
||||
"touchedtime",
|
||||
"toupper",
|
||||
"Tpng",
|
||||
"treatedconsent",
|
||||
"treateddirectmanager",
|
||||
"Treateds",
|
||||
"tsbuild",
|
||||
"Tpng",
|
||||
"Tsvg",
|
||||
"twentypercent",
|
||||
"typeahead",
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
closeOldRequest,
|
||||
} from '../../../routes/settings/approvals';
|
||||
import { getProviders } from '../../../transitional';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { IProviders, ReposAppRequest } from '../../../interfaces';
|
|||
import { jsonError } from '../../../middleware';
|
||||
import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment';
|
||||
import { ErrorHelper, getProviders } from '../../../transitional';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
import routeApprovals from './approvals';
|
||||
import routeIndividualContextualOrganization from './organization';
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
} from '../../../../interfaces';
|
||||
import { jsonError } from '../../../../middleware';
|
||||
import getCompanySpecificDeployment from '../../../../middleware/companySpecificDeployment';
|
||||
import { IndividualContext } from '../../../../user';
|
||||
import { IndividualContext } from '../../../../business/user';
|
||||
|
||||
import RouteRepos from './repos';
|
||||
import RouteTeams from './teams';
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
getContextualRepository,
|
||||
getContextualRepositoryPermissions,
|
||||
} from '../../../../middleware/github/repoPermissions';
|
||||
import { IndividualContext } from '../../../../user';
|
||||
import { IndividualContext } from '../../../../business/user';
|
||||
import { ErrorHelper, getProviders } from '../../../../transitional';
|
||||
import NewRepositoryLockdownSystem from '../../../../features/newRepositories/newRepositoryLockdown';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { jsonError } from '../../../../middleware';
|
|||
import { setContextualRepository } from '../../../../middleware/github/repoPermissions';
|
||||
|
||||
import { OrganizationMembershipState, ReposAppRequest } from '../../../../interfaces';
|
||||
import { IndividualContext } from '../../../../user';
|
||||
import { IndividualContext } from '../../../../business/user';
|
||||
import { createRepositoryFromClient } from '../../newOrgRepo';
|
||||
|
||||
import RouteContextualRepo from './repo';
|
||||
|
|
|
@ -25,7 +25,7 @@ import { submitTeamJoinRequest } from '../../../../routes/org/team';
|
|||
import { postActionDecision, TeamApprovalDecision } from '../../../../routes/org/team/approval';
|
||||
import { PermissionWorkflowEngine } from '../../../../routes/org/team/approvals';
|
||||
import { getProviders } from '../../../../transitional';
|
||||
import { IndividualContext } from '../../../../user';
|
||||
import { IndividualContext } from '../../../../business/user';
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import asyncHandler from 'express-async-handler';
|
||||
|
||||
import { ReposAppRequest } from '../../../interfaces';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
export default asyncHandler(async (req: ReposAppRequest, res) => {
|
||||
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import asyncHandler from 'express-async-handler';
|
||||
|
||||
import { GitHubRepositoryPermission, ReposAppRequest } from '../../../interfaces';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
export default asyncHandler(async (req: ReposAppRequest, res, next) => {
|
||||
try {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { sendLinkedAccountMail } from '../../../business/operations/link';
|
|||
import { ReposAppRequest } from '../../../interfaces';
|
||||
import { jsonError } from '../../../middleware';
|
||||
import { CreateError, getProviders } from '../../../transitional';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import asyncHandler from 'express-async-handler';
|
||||
|
||||
import { ReposAppRequest, TeamJsonFormat } from '../../../interfaces';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
export default asyncHandler(async (req: ReposAppRequest, res, next) => {
|
||||
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
|
||||
|
|
|
@ -17,7 +17,8 @@ import { getProviders } from '../../transitional';
|
|||
|
||||
import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment';
|
||||
|
||||
import { ReposAppRequest } from '../../interfaces';
|
||||
import type { ReposAppRequest } from '../../interfaces';
|
||||
import type { IndividualContext } from '../../business/user';
|
||||
|
||||
import routeClientNewRepo from './newRepo';
|
||||
import routeContext from './context';
|
||||
|
@ -61,6 +62,64 @@ router.use('/news', routeNews);
|
|||
const dynamicStartupInstance = getCompanySpecificDeployment();
|
||||
dynamicStartupInstance?.routes?.api?.index && dynamicStartupInstance?.routes?.api?.index(router);
|
||||
|
||||
router.get('/', (req: ReposAppRequest, res) => {
|
||||
const { config } = getProviders(req);
|
||||
const runtimeConfiguration = req.app.runtimeConfiguration;
|
||||
|
||||
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
|
||||
const isGitHubAuthenticated = !!activeContext.getSessionBasedGitHubIdentity()?.id;
|
||||
const data = {
|
||||
deployment: config.continuousDeployment,
|
||||
frontend: runtimeConfiguration?.client || {},
|
||||
hosting: {
|
||||
app: config?.web?.app,
|
||||
baseUrl: config?.webServer?.baseUrl,
|
||||
server: {
|
||||
port: config?.webServer?.port,
|
||||
hostname: req.hostname,
|
||||
},
|
||||
appService: config?.webServer?.appService?.name
|
||||
? {
|
||||
name: config?.webServer?.appService?.name,
|
||||
slot: config?.webServer?.appService?.slot,
|
||||
region: config?.webServer?.appService?.region,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
runtime: {
|
||||
node: {
|
||||
environment: config?.node?.environment,
|
||||
version: config?.node?.version,
|
||||
},
|
||||
},
|
||||
development: {
|
||||
githubCodespacesConnected: config?.github?.codespaces?.connected === true ? true : undefined,
|
||||
githubCodespacesName: config?.github?.codespaces?.name,
|
||||
},
|
||||
app: {
|
||||
environment: config?.environment?.name,
|
||||
appName: config?.web?.app,
|
||||
},
|
||||
session: {
|
||||
corporateIdentity: activeContext.corporateIdentity,
|
||||
githubIdentity: activeContext.getGitHubIdentity(),
|
||||
isAuthenticated: true,
|
||||
isGitHubAuthenticated,
|
||||
isLinked: !!activeContext.link,
|
||||
hasAdditionalLinks: activeContext.hasAdditionalLinks,
|
||||
impersonation: config.impersonation?.corporateId
|
||||
? {
|
||||
corporateId: config.impersonation.corporateId,
|
||||
githubId: config.impersonation.githubId,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
res.contentType('application/json');
|
||||
return res.send(JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
router.use((req, res, next) => {
|
||||
return next(jsonError('The resource or endpoint you are looking for is not there', 404));
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { Router } from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { jsonError } from '../../middleware';
|
||||
import { ErrorHelper, getProviders } from '../../transitional';
|
||||
import { unlinkInteractive } from '../../routes/unlink';
|
||||
|
|
|
@ -11,7 +11,7 @@ import _ from 'lodash';
|
|||
|
||||
import { getProviders } from '../../transitional';
|
||||
import { jsonError } from '../../middleware/jsonError';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { Organization } from '../../business/organization';
|
||||
import { CreateRepository, ICreateRepositoryApiResult, CreateRepositoryEntrypoint } from '../createRepo';
|
||||
import { Team } from '../../business/team';
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
OrganizationAnnotation,
|
||||
} from '../../../entities/organizationAnnotation';
|
||||
import { ErrorHelper, getProviders } from '../../../transitional';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
import { IProviders } from '../../../interfaces';
|
||||
|
||||
const router: Router = Router();
|
||||
|
|
|
@ -9,7 +9,7 @@ import asyncHandler from 'express-async-handler';
|
|||
import { jsonError } from '../../../middleware';
|
||||
import { ErrorHelper, getProviders } from '../../../transitional';
|
||||
import { Repository } from '../../../business';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
import NewRepositoryLockdownSystem from '../../../features/newRepositories/newRepositoryLockdown';
|
||||
import {
|
||||
AddRepositoryPermissionsToRequest,
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
IApprovalPackage,
|
||||
} from '../routes/org/repoWorkflowEngine';
|
||||
import { IMailProvider } from '../lib/mailProvider';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
import NewRepositoryLockdownSystem from '../features/newRepositories/newRepositoryLockdown';
|
||||
import {
|
||||
ICreateRepositoryResult,
|
||||
|
|
81
api/index.ts
81
api/index.ts
|
@ -9,18 +9,16 @@ const router: Router = Router();
|
|||
|
||||
import cors from 'cors';
|
||||
|
||||
import { getProviders } from '../transitional';
|
||||
import { CreateError, getProviders } from '../transitional';
|
||||
|
||||
import { jsonError } from '../middleware';
|
||||
import { IApiRequest } from '../middleware/apiReposAuth';
|
||||
|
||||
import apiExtension from './extension';
|
||||
import apiClient from './client/';
|
||||
import apiWebhook from './webhook';
|
||||
|
||||
import apiPeople from './people';
|
||||
|
||||
import AadApiAuthentication from '../middleware/apiAad';
|
||||
import AadApiAuthentication, { requireAadApiAuthorizedScope } from '../middleware/apiAad';
|
||||
import AzureDevOpsAuthenticationMiddleware from '../middleware/apiVstsAuth';
|
||||
import ReposApiAuthentication from '../middleware/apiReposAuth';
|
||||
import { CreateRepository, CreateRepositoryEntrypoint } from './createRepo';
|
||||
|
@ -31,10 +29,20 @@ import { ReposAppRequest } from '../interfaces';
|
|||
|
||||
const hardcodedApiVersions = ['2019-10-01', '2019-02-01', '2017-09-01', '2017-03-08', '2016-12-01'];
|
||||
|
||||
router.use('/client', apiClient);
|
||||
function isClientRoute(req: ReposAppRequest) {
|
||||
const path = req.path.toLowerCase();
|
||||
return path.startsWith('/client');
|
||||
}
|
||||
|
||||
router.use('/webhook', apiWebhook);
|
||||
|
||||
router.use((req: IApiRequest, res, next) => {
|
||||
if (isClientRoute(req)) {
|
||||
// The frontend client routes are hooked into Express after
|
||||
// the session middleware. The client route does not require
|
||||
// an API version.
|
||||
return next();
|
||||
}
|
||||
const apiVersion = (req.query['api-version'] || req.headers['api-version']) as string;
|
||||
if (!apiVersion) {
|
||||
return next(jsonError('This endpoint requires that an API Version be provided.', 422));
|
||||
|
@ -75,35 +83,36 @@ router.use('/extension', cors(), multipleProviders, apiExtension);
|
|||
const dynamicStartupInstance = getCompanySpecificDeployment();
|
||||
dynamicStartupInstance?.routes?.api?.index && dynamicStartupInstance?.routes?.api?.rootIndex(router);
|
||||
|
||||
router.use('/:org', aadAndCustomProviders);
|
||||
//-----------------------------------------------------------------------------
|
||||
// Create repository API
|
||||
//-----------------------------------------------------------------------------
|
||||
router.post('/:org/repos', aadAndCustomProviders);
|
||||
|
||||
router.use('/:org', function (req: IApiRequest, res, next) {
|
||||
const orgName = req.params.org;
|
||||
if (!req.apiKeyToken.organizationScopes) {
|
||||
return next(jsonError('There is a problem with the key configuration (no organization scopes)', 412));
|
||||
}
|
||||
// '*'' is authorized for all organizations in this configuration environment
|
||||
if (!req.apiKeyToken.hasOrganizationScope(orgName)) {
|
||||
return next(jsonError('The key is not authorized for this organization', 401));
|
||||
}
|
||||
if (!req.apiKeyToken.scopes) {
|
||||
return next(jsonError('There is a problem with the key configuration (no specific API scopes)', 412));
|
||||
}
|
||||
if (!req.apiKeyToken.hasScope('createRepo')) {
|
||||
return next(jsonError('The key is not authorized to use the repo create APIs', 401));
|
||||
}
|
||||
router.post(
|
||||
'/:org/repos',
|
||||
requireAadApiAuthorizedScope('createRepo'),
|
||||
function (req: IApiRequest, res, next) {
|
||||
const orgName = req.params.org;
|
||||
if (!req.apiKeyToken.organizationScopes) {
|
||||
return next(jsonError('There is a problem with the key configuration (no organization scopes)', 412));
|
||||
}
|
||||
// '*'' is authorized for all organizations in this configuration environment
|
||||
if (!req.apiKeyToken.hasOrganizationScope(orgName)) {
|
||||
return next(jsonError('The key is not authorized for this organization', 401));
|
||||
}
|
||||
|
||||
const providers = getProviders(req);
|
||||
const operations = providers.operations;
|
||||
let organization = null;
|
||||
try {
|
||||
organization = operations.getOrganization(orgName);
|
||||
} catch (ex) {
|
||||
return next(jsonError(ex, 400));
|
||||
const providers = getProviders(req);
|
||||
const operations = providers.operations;
|
||||
let organization = null;
|
||||
try {
|
||||
organization = operations.getOrganization(orgName);
|
||||
} catch (ex) {
|
||||
return next(jsonError(ex, 400));
|
||||
}
|
||||
req.organization = organization;
|
||||
return next();
|
||||
}
|
||||
req.organization = organization;
|
||||
return next();
|
||||
});
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/:org/repos',
|
||||
|
@ -176,6 +185,16 @@ router.post(
|
|||
})
|
||||
);
|
||||
|
||||
router.use((req: IApiRequest, res, next) => {
|
||||
if (isClientRoute(req)) {
|
||||
// The frontend client routes are hooked into Express after
|
||||
// the session middleware. The client route does not require
|
||||
// an API version.
|
||||
return next();
|
||||
}
|
||||
return next(CreateError.NotFound('The API endpoint was not found.'));
|
||||
});
|
||||
|
||||
router.use(JsonErrorHandler);
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as common from './common';
|
|||
import { wrapError } from '../utils';
|
||||
import { corporateLinkToJson } from './corporateLink';
|
||||
import { Organization } from './organization';
|
||||
import { AppPurpose } from '../github';
|
||||
import { AppPurpose } from './githubApps';
|
||||
import { ILinkProvider } from '../lib/linkProviders';
|
||||
import { CacheDefault, getMaxAgeSeconds } from '.';
|
||||
import {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import { Organization } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -8,7 +8,7 @@ import { createAppAuth, InstallationAccessTokenAuthentication } from '@octokit/a
|
|||
import { AppAuthentication, AuthInterface } from '@octokit/auth-app/dist-types/types';
|
||||
|
||||
import { AppPurposeTypes, ICustomAppPurpose } from '.';
|
||||
import { IAuthorizationHeaderValue } from '../interfaces';
|
||||
import { IAuthorizationHeaderValue } from '../../interfaces';
|
||||
|
||||
import Debug from 'debug';
|
||||
const debug = Debug('github:tokens');
|
|
@ -3,8 +3,8 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { IReposApplication } from '../interfaces';
|
||||
import { CreateError } from '../transitional';
|
||||
import { IReposApplication } from '../../interfaces';
|
||||
import { CreateError } from '../../transitional';
|
||||
|
||||
import Debug from 'debug';
|
||||
const debug = Debug('github:tokens');
|
|
@ -17,11 +17,11 @@ import {
|
|||
getAppPurposeId,
|
||||
} from '.';
|
||||
import { GitHubAppTokens } from './appTokens';
|
||||
import { IAuthorizationHeaderValue, NoCacheNoBackground } from '../interfaces';
|
||||
import { OrganizationSetting } from '../entities/organizationSettings/organizationSetting';
|
||||
import { readFileToText } from '../utils';
|
||||
import { Operations, OperationsCore, Organization } from '../business';
|
||||
import { CreateError } from '../transitional';
|
||||
import { IAuthorizationHeaderValue, NoCacheNoBackground } from '../../interfaces';
|
||||
import { OrganizationSetting } from '../../entities/organizationSettings/organizationSetting';
|
||||
import { readFileToText } from '../../utils';
|
||||
import { Operations, OperationsCore, Organization } from '..';
|
||||
import { CreateError } from '../../transitional';
|
||||
|
||||
export interface IGitHubRateLimit {
|
||||
limit: number;
|
|
@ -4,8 +4,8 @@
|
|||
//
|
||||
|
||||
import { OrganizationSetting } from '../../entities/organizationSettings/organizationSetting';
|
||||
import { GitHubAppAuthenticationType, AppPurpose, ICustomAppPurpose, AppPurposeTypes } from '../../github';
|
||||
import { GitHubTokenManager } from '../../github/tokenManager';
|
||||
import { GitHubAppAuthenticationType, AppPurpose, ICustomAppPurpose, AppPurposeTypes } from '../githubApps';
|
||||
import { GitHubTokenManager } from '../githubApps/tokenManager';
|
||||
import {
|
||||
IProviders,
|
||||
ICacheDefaultTimes,
|
||||
|
|
|
@ -9,7 +9,7 @@ import throat from 'throat';
|
|||
import { Account } from '../account';
|
||||
import { GraphManager } from '../graphManager';
|
||||
import { IGitHubOrganizationResponse, Organization } from '../organization';
|
||||
import { GitHubTokenManager } from '../../github/tokenManager';
|
||||
import { GitHubTokenManager } from '../githubApps/tokenManager';
|
||||
import RenderHtmlMail from '../../lib/emailRender';
|
||||
import { wrapError, sortByCaseInsensitive } from '../../utils';
|
||||
import { Repository } from '../repository';
|
||||
|
@ -20,7 +20,7 @@ import {
|
|||
GitHubAppAuthenticationType,
|
||||
GitHubAppPurposes,
|
||||
IGitHubAppConfiguration,
|
||||
} from '../../github';
|
||||
} from '../githubApps';
|
||||
import {
|
||||
OrganizationFeature,
|
||||
OrganizationSetting,
|
||||
|
|
|
@ -13,7 +13,7 @@ import { Repository } from './repository';
|
|||
import { wrapError } from '../utils';
|
||||
import { StripGitHubEntity } from '../lib/github/restApi';
|
||||
import { GitHubResponseType } from '../lib/github/endpointEntities';
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import {
|
||||
OrganizationFeature,
|
||||
OrganizationSetting,
|
||||
|
@ -63,7 +63,7 @@ import { CreateError, ErrorHelper } from '../transitional';
|
|||
import { jsonError } from '../middleware';
|
||||
import getCompanySpecificDeployment from '../middleware/companySpecificDeployment';
|
||||
import { ConfigGitHubTemplates } from '../config/github.templates.types';
|
||||
import { GitHubTokenManager } from '../github/tokenManager';
|
||||
import { GitHubTokenManager } from './githubApps/tokenManager';
|
||||
import { OrganizationProjects } from './projects';
|
||||
import { OrganizationDomains } from './domains';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import { Organization, Repository } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import { Organization } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import { Organization } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
RepositoryIssue,
|
||||
} from '.';
|
||||
import { RepositoryMetadataEntity } from '../entities/repositoryMetadata/repositoryMetadata';
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import {
|
||||
IPurposefulGetAuthorizationHeader,
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Repository } from './repository';
|
||||
import { getPageSize, getMaxAgeSeconds, CacheDefault } from '.';
|
||||
import { AppPurpose } from '../github';
|
||||
import { AppPurpose } from './githubApps';
|
||||
import {
|
||||
IPurposefulGetAuthorizationHeader,
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Repository } from './repository';
|
||||
import { wrapError } from '../utils';
|
||||
import { AppPurpose } from '../github';
|
||||
import { AppPurpose } from './githubApps';
|
||||
import { CacheDefault, getMaxAgeSeconds, Operations } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Repository } from './repository';
|
||||
import { wrapError } from '../utils';
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import { CacheDefault, getMaxAgeSeconds } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { AppPurpose } from '../github';
|
||||
import { AppPurpose } from './githubApps';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
IPurposefulGetAuthorizationHeader,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
|
||||
import { CacheDefault, getMaxAgeSeconds, RepositoryIssue } from '.';
|
||||
import { AppPurpose, AppPurposeTypes } from '../github';
|
||||
import { AppPurpose, AppPurposeTypes } from './githubApps';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
IPurposefulGetAuthorizationHeader,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Repository } from './repository';
|
||||
import { wrapError } from '../utils';
|
||||
import { AppPurpose } from '../github';
|
||||
import { AppPurpose } from './githubApps';
|
||||
import { CacheDefault, getMaxAgeSeconds } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -13,7 +13,7 @@ import { TeamMember } from './teamMember';
|
|||
import { TeamRepositoryPermission } from './teamRepositoryPermission';
|
||||
import { IApprovalProvider } from '../entities/teamJoinApproval/approvalProvider';
|
||||
import { TeamJoinApprovalEntity } from '../entities/teamJoinApproval/teamJoinApproval';
|
||||
import { AppPurpose } from '../github';
|
||||
import { AppPurpose } from './githubApps';
|
||||
import { CacheDefault, getMaxAgeSeconds, getPageSize, Organization } from '.';
|
||||
import {
|
||||
IOperationsInstance,
|
||||
|
|
|
@ -10,16 +10,16 @@ import {
|
|||
Repository,
|
||||
Team,
|
||||
TeamRepositoryPermission,
|
||||
} from '../business';
|
||||
import QueryCache from '../business/queryCache';
|
||||
} from '..';
|
||||
import QueryCache from '../queryCache';
|
||||
import {
|
||||
IQueryCacheTeamRepositoryPermission,
|
||||
OrganizationMembershipRole,
|
||||
GitHubTeamRole,
|
||||
OrganizationMembershipRoleQuery,
|
||||
GitHubRepositoryPermission,
|
||||
} from '../interfaces';
|
||||
import { SettleToStateValue, isPermissionBetterThan, ErrorHelper } from '../transitional';
|
||||
} from '../../interfaces';
|
||||
import { SettleToStateValue, isPermissionBetterThan, ErrorHelper } from '../../transitional';
|
||||
import LinkManager from './linkManager';
|
||||
|
||||
// PLANNING once consolidated
|
|
@ -10,8 +10,8 @@ import objectPath from 'object-path';
|
|||
import Debug from 'debug';
|
||||
const debug = Debug.debug('context');
|
||||
|
||||
import { addBreadcrumb, isCodespacesAuthenticating } from '../utils';
|
||||
import { Operations } from '../business/operations';
|
||||
import { addBreadcrumb, isCodespacesAuthenticating } from '../../utils';
|
||||
import { Operations } from '../operations';
|
||||
import { UserContext } from './aggregate';
|
||||
import {
|
||||
ReposAppRequest,
|
||||
|
@ -21,7 +21,7 @@ import {
|
|||
IAppSession,
|
||||
ICorporateLink,
|
||||
IDictionary,
|
||||
} from '../interfaces';
|
||||
} from '../../interfaces';
|
||||
|
||||
// - - - identity
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { Operations } from '../business/operations';
|
||||
import { Operations } from '../operations';
|
||||
|
||||
export default class LinkManager {
|
||||
private _context: any;
|
|
@ -10,5 +10,5 @@ export type ConfigRootAuthentication = {
|
|||
};
|
||||
|
||||
export type ConfigAuthentication = ConfigRootAuthenticationVsts & {
|
||||
scheme: 'aad' | 'github';
|
||||
scheme: 'aad' | 'github' | 'oauth2';
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ export type ConfigNewsArticleAction = {
|
|||
export type ConfigNewsArticle = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
ignore: boolean;
|
||||
paragraphs: string[];
|
||||
actions: ConfigNewsArticleAction[];
|
||||
};
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// Copyright (c) Microsoft.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function (graphApi) {
|
||||
const environment = graphApi.environment.get('NODE_ENV');
|
||||
return {
|
||||
environment,
|
||||
isProduction: environment === 'production',
|
||||
version: process.version,
|
||||
};
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"environment": "env://NODE_ENV",
|
||||
"isProduction": "env://NODE_ENV?trueIf=production"
|
||||
}
|
|
@ -9,5 +9,6 @@ export type ConfigRootNode = {
|
|||
|
||||
export type ConfigNode = {
|
||||
environment: string;
|
||||
version: string;
|
||||
isProduction: boolean;
|
||||
};
|
||||
|
|
|
@ -23,9 +23,15 @@ import {
|
|||
PostgresJsonEntityQuery,
|
||||
PostgresSettings,
|
||||
} from '../../lib/entityMetadataProvider/postgres';
|
||||
import type { ApiClientGroupDisplay } from '../../interfaces/api';
|
||||
|
||||
const type = Type;
|
||||
|
||||
export type TokenAadAppInformation = {
|
||||
clientId: string;
|
||||
objectId: string;
|
||||
};
|
||||
|
||||
interface ITokenEntityProperties {
|
||||
token: any;
|
||||
active: any;
|
||||
|
@ -56,6 +62,7 @@ const fieldNames = Object.getOwnPropertyNames(Field);
|
|||
|
||||
export class PersonalAccessToken implements IObjectWithDefinedKeys, ITokenEntityProperties {
|
||||
private _key: string;
|
||||
private _aadInfo: TokenAadAppInformation;
|
||||
|
||||
token: string;
|
||||
|
||||
|
@ -75,12 +82,23 @@ export class PersonalAccessToken implements IObjectWithDefinedKeys, ITokenEntity
|
|||
this.created = new Date();
|
||||
}
|
||||
|
||||
static CreateFromAadAuthorization({ appId, oid, scopes, organizationScopes }): PersonalAccessToken {
|
||||
static CreateFromAadAuthorization(
|
||||
{ appId, oid, scopes, organizationScopes },
|
||||
optionalDisplayValues: ApiClientGroupDisplay
|
||||
): PersonalAccessToken {
|
||||
const pat = new PersonalAccessToken();
|
||||
pat._aadInfo = {
|
||||
clientId: appId,
|
||||
objectId: oid,
|
||||
};
|
||||
pat.corporateId = null;
|
||||
pat.description = `AAD oid ${oid} app ${appId} with scopes ${scopes}`;
|
||||
pat.source = `AAD oid ${oid} app ${appId}`;
|
||||
pat.displayUsername = 'AAD Identity';
|
||||
pat.displayUsername = optionalDisplayValues?.displayName
|
||||
? `${optionalDisplayValues.displayName}${
|
||||
optionalDisplayValues.contactAddress ? ' (' + optionalDisplayValues.contactAddress + ')' : ''
|
||||
}`
|
||||
: 'AAD Identity';
|
||||
pat.organizationScopes = organizationScopes;
|
||||
pat.scopes = scopes;
|
||||
return pat;
|
||||
|
@ -110,6 +128,10 @@ export class PersonalAccessToken implements IObjectWithDefinedKeys, ITokenEntity
|
|||
return pat;
|
||||
}
|
||||
|
||||
getAadInformation(): TokenAadAppInformation {
|
||||
return this._aadInfo;
|
||||
}
|
||||
|
||||
getObjectFieldNames(): string[] {
|
||||
return fieldNames;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Repository } from '../../business';
|
||||
import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { validateUserCanSelfDeleteRepository } from './validateSelfServiceDelete';
|
||||
import { validateUserCanConfigureRepository } from './validateSelfServiceSetup';
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import { DateTime } from 'luxon';
|
|||
import { Repository } from '../../business';
|
||||
import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata';
|
||||
import { RepositoryLockdownState } from '../../interfaces';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { daysInMilliseconds } from '../../utils';
|
||||
|
||||
export async function validateUserCanSelfDeleteRepository(
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata';
|
||||
import { RepositoryLockdownState } from '../../interfaces';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
|
||||
export async function validateUserCanConfigureRepository(
|
||||
metadata: RepositoryMetadataEntity,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Team } from '../business';
|
||||
import { Operations } from '../business';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
import { addArrayToSet } from '../utils';
|
||||
import { IMail } from '../lib/mailProvider';
|
||||
import {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Copyright (c) Microsoft.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
export type ApiClientGroupDisplay = {
|
||||
displayName: string;
|
||||
contactAddress: string;
|
||||
};
|
|
@ -6,6 +6,8 @@
|
|||
import { Application } from 'express';
|
||||
import { IProviders } from './providers';
|
||||
|
||||
import type { RuntimeConfiguration } from './config';
|
||||
|
||||
export interface IApplicationProfile {
|
||||
applicationName: string;
|
||||
customErrorHandlerRender?: (errorView: any, err: Error, req: any, res: any, next: any) => Promise<void>;
|
||||
|
@ -28,6 +30,7 @@ export interface IReposApplication extends Application {
|
|||
config: any;
|
||||
isBackgroundJob: boolean;
|
||||
enableAllGitHubApps: boolean;
|
||||
runtimeConfiguration: RuntimeConfiguration;
|
||||
|
||||
startServer: () => Promise<void>;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
export interface ICompanySpecificFeatureDemo {
|
||||
isDemoUser: (activeContext: IndividualContext) => boolean;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Organization } from '../../../business';
|
||||
import { IProviders } from '../../../interfaces';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
export interface ICompanySpecificFeatureOrganizationJoinAcl {
|
||||
tryAuthorizeOrganizationJoin: (
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { IProviders, LocalApiRepoAction } from '../..';
|
||||
import { Repository } from '../../../business';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
|
||||
export interface ICompanySpecificRepositoryStateStatus {}
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
import { Repository, Team } from '../../business';
|
||||
import { IContextualRepositoryPermissions } from '../../middleware/github/repoPermissions';
|
||||
import { IProviders, ReposAppRequest } from '../../interfaces';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { IRequestTeamPermissions } from '../../middleware/github/teamPermissions';
|
||||
import type { ApiClientGroupDisplay } from '../api';
|
||||
|
||||
export interface ICompanySpecificRepoPermissionsMiddlewareCalls {
|
||||
afterPermissionsInitialized?: (
|
||||
|
@ -39,6 +40,16 @@ export interface ICompanySpecificTeamPermissionsMiddlewareCalls {
|
|||
|
||||
export interface ICompanySpecificAuthenticationCalls {
|
||||
shouldRedirectToSignIn?: (providers: IProviders, req: ReposAppRequest) => Promise<boolean>;
|
||||
getAadApiAuthenticationValidator?(providers: IProviders): IAadAuthenticationValidator;
|
||||
}
|
||||
|
||||
export interface IAadAuthenticationValidator {
|
||||
isAuthorizedTenant(tenantId: string): Promise<boolean>;
|
||||
getAudienceIdentities(): Promise<string[]>;
|
||||
getAuthorizedClientIdToken(clientId: string): Promise<any>;
|
||||
getAuthorizedObjectIdToken(objectId: string): Promise<any>;
|
||||
getScopes(tokenRepresentation: any): Promise<string[]>;
|
||||
getDisplayValues(tokenRepresentation: any): Promise<ApiClientGroupDisplay>;
|
||||
}
|
||||
|
||||
export interface IAttachCompanySpecificMiddleware {
|
||||
|
|
|
@ -5,3 +5,6 @@
|
|||
|
||||
import type { SiteConfiguration } from '../config/index.types';
|
||||
export type { SiteConfiguration };
|
||||
|
||||
import type { RootRuntimeConfigurationClient } from '../middleware/staticClientApp2';
|
||||
export type RuntimeConfiguration = RootRuntimeConfigurationClient;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { AppPurposeTypes } from '../../github';
|
||||
import { AppPurposeTypes } from '../../business/githubApps';
|
||||
|
||||
export interface ICacheOptions {
|
||||
backgroundRefresh?: any | null | undefined;
|
||||
|
|
|
@ -7,8 +7,11 @@ import { Session } from 'express-session';
|
|||
import { Request, Response } from 'express';
|
||||
import { AccessToken } from 'simple-oauth2';
|
||||
|
||||
import type { TelemetryClient } from 'applicationinsights';
|
||||
import type { IReposApplication } from './app';
|
||||
|
||||
import { Organization, Team } from '../business';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
|
||||
export enum UserAlertType {
|
||||
Success = 'success',
|
||||
|
@ -40,8 +43,10 @@ export interface ReposAppRequest extends Request {
|
|||
isAuthenticated(): boolean;
|
||||
user: any;
|
||||
|
||||
app: IReposApplication;
|
||||
|
||||
// our extensions
|
||||
insights?: any;
|
||||
insights?: TelemetryClient;
|
||||
reposContext?: IReposAppContext;
|
||||
currentOrganizationMemberships?: any; // needs a redesign
|
||||
teamsPagerMode?: string;
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
IPurposefulGetAuthorizationHeader,
|
||||
ITeamMembershipOptions,
|
||||
} from '../../interfaces';
|
||||
import { AppPurpose } from '../../github';
|
||||
import { AppPurpose } from '../../business/githubApps';
|
||||
|
||||
interface IOrganizationsResponse extends IRestResponse {
|
||||
orgs?: any;
|
||||
|
|
|
@ -15,7 +15,7 @@ import { CrossOrganizationCollator } from './crossOrganization';
|
|||
import { LinkMethods } from './links';
|
||||
import { IGetAuthorizationHeader, IAuthorizationHeaderValue } from '../../interfaces';
|
||||
import { ICacheHelper } from '../caching';
|
||||
import { ICustomAppPurpose } from '../../github';
|
||||
import { ICustomAppPurpose } from '../../business/githubApps';
|
||||
|
||||
export enum CacheMode {
|
||||
ValidateCache = 'ValidateCache',
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
//
|
||||
// Copyright (c) Microsoft.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { getAadApiConfiguration } from './apiAad';
|
||||
|
||||
describe('AAD API Configuration', () => {
|
||||
let standardConfig = {};
|
||||
let stringConfig = {};
|
||||
|
||||
beforeEach(() => {
|
||||
standardConfig = {
|
||||
microsoft: {
|
||||
api: {
|
||||
aad: {
|
||||
authorizedTenants: 't1,t2',
|
||||
apiAppScope: 'api://app',
|
||||
approvedApps: {
|
||||
scopes: {
|
||||
create: {
|
||||
repos: ['a1'],
|
||||
},
|
||||
},
|
||||
},
|
||||
approvedOids: {
|
||||
scopes: {
|
||||
create: {
|
||||
repos: ['o1'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
stringConfig = {
|
||||
microsoft: {
|
||||
api: {
|
||||
aad: {
|
||||
authorizedTenants: 't1,t2',
|
||||
apiAppScope: 'api://app',
|
||||
approvedApps: {
|
||||
scopes: {
|
||||
create: {
|
||||
repos: 'a1,a2,a3',
|
||||
},
|
||||
},
|
||||
},
|
||||
approvedOids: {
|
||||
scopes: {
|
||||
create: {
|
||||
repos: 'o1,o2',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
test('OID and app ID string values parse', () => {
|
||||
getAadApiConfiguration(stringConfig);
|
||||
});
|
||||
test('OID and app ID arrays work', () => {
|
||||
getAadApiConfiguration(standardConfig);
|
||||
});
|
||||
});
|
|
@ -9,24 +9,22 @@ import jwksClient from 'jwks-rsa';
|
|||
import { isJsonError, jsonError } from './jsonError';
|
||||
import { IApiRequest, wrapErrorForImmediateUserError } from './apiReposAuth';
|
||||
import { PersonalAccessToken } from '../entities/token/token';
|
||||
import { CreateError, getProviders, splitSemiColonCommas } from '../transitional';
|
||||
import { CreateError, getProviders } from '../transitional';
|
||||
import getCompanySpecificDeployment from './companySpecificDeployment';
|
||||
|
||||
// TODO: Caching of signing keys
|
||||
// CONSIDER: Caching of signing keys
|
||||
|
||||
interface IConfigAadApiApprovedAppsOrOids {
|
||||
scopes: {
|
||||
read: {
|
||||
links: string[] | string;
|
||||
maintainers: string[] | string;
|
||||
'microsoft-github-policy-service': string[] | string;
|
||||
};
|
||||
create: {
|
||||
repos: string[] | string;
|
||||
};
|
||||
export function requireAadApiAuthorizedScope(scope: string) {
|
||||
return (req: IApiRequest, res, next) => {
|
||||
const { apiKeyToken } = req;
|
||||
if (!apiKeyToken.hasScope(scope)) {
|
||||
return next(jsonError(`Not authorized for ${scope}`, 403));
|
||||
}
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
export default function AadApiMiddleware(req: IApiRequest, res, next) {
|
||||
export default function aadApiMiddleware(req: IApiRequest, res, next) {
|
||||
return validateAadAuthorization(req)
|
||||
.then((ok) => {
|
||||
return next();
|
||||
|
@ -65,142 +63,8 @@ function getSigningKeys(header, callback) {
|
|||
});
|
||||
}
|
||||
|
||||
export function getAadApiConfiguration(config: any) {
|
||||
const allowedTenants = Array.isArray(config?.microsoft?.api?.aad?.authorizedTenants)
|
||||
? config.microsoft.api.aad.authorizedTenants
|
||||
: (config?.microsoft?.api?.aad?.authorizedTenants || '').split(',');
|
||||
if (!allowedTenants) {
|
||||
throw jsonError('App not configured for authorizing specific tenants', 500);
|
||||
}
|
||||
|
||||
let reposApiAudienceIdentities = config?.microsoft?.api?.aad?.apiAppScopes
|
||||
? (config.microsoft.api.aad.apiAppScopes as string).split(',')
|
||||
: null;
|
||||
if (!reposApiAudienceIdentities) {
|
||||
const reposApiAudienceIdentity = config?.microsoft?.api?.aad?.apiAppScope
|
||||
? [config.microsoft.api.aad.apiAppScope]
|
||||
: null;
|
||||
if (!reposApiAudienceIdentity) {
|
||||
throw jsonError('App not configured for authorizing APIs via AAD', 500);
|
||||
}
|
||||
reposApiAudienceIdentities = reposApiAudienceIdentity;
|
||||
}
|
||||
if (!reposApiAudienceIdentities) {
|
||||
throw jsonError('App not configured for authorizing APIs via AAD', 500);
|
||||
}
|
||||
|
||||
const approvedApps = config?.microsoft?.api?.aad?.approvedApps as IConfigAadApiApprovedAppsOrOids;
|
||||
if (approvedApps === undefined) {
|
||||
throw jsonError('AAD API app authentication is not configured', 500);
|
||||
}
|
||||
|
||||
const approvedOids = config?.microsoft?.api?.aad?.approvedOids as IConfigAadApiApprovedAppsOrOids;
|
||||
if (approvedApps === undefined) {
|
||||
throw jsonError('AAD API OID authentication is not configured', 500);
|
||||
}
|
||||
|
||||
// Any app that has a valid scope can call the API, but may not be scoped and will error out in the API tier
|
||||
const approvedAppsToCreateRepos = Array.isArray(approvedApps?.scopes?.create?.repos)
|
||||
? approvedApps?.scopes?.create?.repos
|
||||
: approvedApps?.scopes?.create?.repos?.split
|
||||
? [...approvedApps.scopes.create.repos.split(',')]
|
||||
: [];
|
||||
const approvedAppsToReadLinks = Array.isArray(approvedApps?.scopes?.read?.links)
|
||||
? approvedApps?.scopes?.read?.links
|
||||
: approvedApps?.scopes?.read?.links?.split
|
||||
? [...approvedApps.scopes.read.links.split(',')]
|
||||
: [];
|
||||
const approvedAppsToReadMaintainers = Array.isArray(approvedApps?.scopes?.read?.maintainers)
|
||||
? approvedApps?.scopes?.read?.maintainers
|
||||
: approvedApps?.scopes?.read?.maintainers?.split
|
||||
? [...approvedApps.scopes.read.maintainers.split(',')]
|
||||
: [];
|
||||
const approvedAppsToReadJitConfirms = Array.isArray(approvedApps?.scopes?.read?.['jit/confirm'])
|
||||
? approvedApps?.scopes?.read?.['jit/confirm']
|
||||
: approvedApps?.scopes?.read?.['jit/confirm']?.split
|
||||
? [...approvedApps.scopes.read['jit/confirm'].split(',')]
|
||||
: [];
|
||||
const microsoftPolicyServiceApiName = 'microsoft-github-policy-service';
|
||||
const approvedAppsToReadPolicyService = parse(approvedApps?.scopes?.read?.[microsoftPolicyServiceApiName]);
|
||||
const approvedOidsToReadPolicyService = parse(approvedOids?.scopes?.read?.[microsoftPolicyServiceApiName]);
|
||||
const approvedOidsToCreateRepos = Array.isArray(approvedOids?.scopes?.create?.repos)
|
||||
? approvedOids?.scopes?.create?.repos
|
||||
: approvedOids?.scopes?.create?.repos?.split
|
||||
? [...(approvedOids?.scopes?.create?.repos ? approvedOids.scopes.create.repos.split(',') : [])]
|
||||
: [];
|
||||
const approvedOidsToReadLinks = Array.isArray(approvedOids?.scopes?.read?.links)
|
||||
? approvedOids?.scopes?.read?.links
|
||||
: approvedOids?.scopes?.read?.links?.split
|
||||
? [...(approvedOids?.scopes?.read?.links ? approvedOids.scopes.read.links.split(',') : [])]
|
||||
: [];
|
||||
const approvedOidsToReadJitConfirms = Array.isArray(approvedOids?.scopes?.read?.['jit/confirm'])
|
||||
? approvedOids?.scopes?.read?.['jit/confirm']
|
||||
: approvedOids?.scopes?.read?.['jit/confirm']?.split
|
||||
? [...approvedOids.scopes.read['jit/confirm'].split(',')]
|
||||
: [];
|
||||
|
||||
const oids = [
|
||||
...approvedOidsToCreateRepos,
|
||||
...approvedOidsToReadLinks,
|
||||
...approvedOidsToReadJitConfirms,
|
||||
...approvedOidsToReadPolicyService,
|
||||
];
|
||||
const appIds = [
|
||||
// hacky temporary design for pulling from config
|
||||
...approvedAppsToCreateRepos,
|
||||
...approvedAppsToReadLinks,
|
||||
...approvedAppsToReadMaintainers,
|
||||
...approvedAppsToReadJitConfirms,
|
||||
...approvedAppsToReadPolicyService,
|
||||
];
|
||||
|
||||
return {
|
||||
allowedTenants,
|
||||
reposApiAudienceIdentities,
|
||||
oids,
|
||||
appIds,
|
||||
approvedAppsToCreateRepos,
|
||||
approvedAppsToReadLinks,
|
||||
approvedAppsToReadMaintainers,
|
||||
approvedOidsToCreateRepos,
|
||||
approvedOidsToReadLinks,
|
||||
approvedAppsToReadJitConfirms,
|
||||
approvedOidsToReadJitConfirms,
|
||||
approvedAppsToReadPolicyService,
|
||||
approvedOidsToReadPolicyService,
|
||||
};
|
||||
}
|
||||
|
||||
function parse(val: string | string[]): string[] {
|
||||
if (Array.isArray(val)) {
|
||||
return val;
|
||||
}
|
||||
if (typeof val === 'string') {
|
||||
return splitSemiColonCommas(val);
|
||||
}
|
||||
if (!val) {
|
||||
return [];
|
||||
}
|
||||
throw CreateError.InvalidParameters('Invalid entries');
|
||||
}
|
||||
|
||||
async function validateAadAuthorization(req: IApiRequest): Promise<void> {
|
||||
const { config, insights } = getProviders(req);
|
||||
const {
|
||||
allowedTenants,
|
||||
reposApiAudienceIdentities,
|
||||
oids,
|
||||
appIds,
|
||||
approvedAppsToCreateRepos,
|
||||
approvedAppsToReadLinks,
|
||||
approvedAppsToReadMaintainers,
|
||||
approvedOidsToCreateRepos,
|
||||
approvedOidsToReadLinks,
|
||||
approvedAppsToReadJitConfirms,
|
||||
approvedOidsToReadJitConfirms,
|
||||
approvedAppsToReadPolicyService,
|
||||
approvedOidsToReadPolicyService,
|
||||
} = getAadApiConfiguration(config);
|
||||
const { insights } = getProviders(req);
|
||||
|
||||
const authorizationHeader = req.headers.authorization;
|
||||
if (!authorizationHeader) {
|
||||
|
@ -224,26 +88,31 @@ async function validateAadAuthorization(req: IApiRequest): Promise<void> {
|
|||
properties: decodedToken as any,
|
||||
});
|
||||
|
||||
const issuer = decodedToken['iss'] as string;
|
||||
let isValidTenant = false;
|
||||
for (let i = 0; isValidTenant === false && i < allowedTenants.length; i++) {
|
||||
const tenant = allowedTenants[i];
|
||||
const stsUrl = `https://sts.windows.net/${tenant}/`;
|
||||
isValidTenant = issuer.startsWith(stsUrl); // support v1.0 or v2.0 as a result
|
||||
const companySpecificDeployment = getCompanySpecificDeployment();
|
||||
const aadApiValidator = companySpecificDeployment?.middleware?.authentication
|
||||
?.getAadApiAuthenticationValidator
|
||||
? companySpecificDeployment.middleware.authentication.getAadApiAuthenticationValidator(
|
||||
getProviders(req)
|
||||
)
|
||||
: null;
|
||||
if (!aadApiValidator) {
|
||||
throw CreateError.InvalidParameters('No AAD API validator');
|
||||
}
|
||||
|
||||
const issuer = decodedToken['iss'] as string;
|
||||
const isValidTenant = aadApiValidator.isAuthorizedTenant(issuer);
|
||||
|
||||
// JWT steps:
|
||||
// [X] aud: needs to match app ID
|
||||
// [X] iss: guid portion is the tenant, confirm it's an approved issuer we want
|
||||
// [X] nbr, exp times (jwt verifies this)
|
||||
// [X] appid: the client app [*we check our list for this]
|
||||
const validationOptions = {
|
||||
audience: reposApiAudienceIdentities,
|
||||
audience: await aadApiValidator.getAudienceIdentities(),
|
||||
issuer,
|
||||
};
|
||||
|
||||
const payload = await callJwtVerify(token, validationOptions);
|
||||
// console.dir(payload);
|
||||
|
||||
if (!isValidTenant) {
|
||||
throw wrapErrorForImmediateUserError(
|
||||
|
@ -252,52 +121,30 @@ async function validateAadAuthorization(req: IApiRequest): Promise<void> {
|
|||
}
|
||||
|
||||
const { appid, oid } = payload as any;
|
||||
let approvedAppMonikerId = await aadApiValidator.getAuthorizedClientIdToken(appid);
|
||||
if (!approvedAppMonikerId) {
|
||||
approvedAppMonikerId = await aadApiValidator.getAuthorizedObjectIdToken(oid);
|
||||
}
|
||||
|
||||
const scopes = [];
|
||||
|
||||
const isAppApproved = appIds.includes(appid);
|
||||
const isOidApproved = oids.includes(oid);
|
||||
const notAuthorized = isAppApproved === false && isOidApproved === false;
|
||||
const notAuthorized = !approvedAppMonikerId;
|
||||
if (notAuthorized) {
|
||||
throw wrapErrorForImmediateUserError(
|
||||
jsonError(`App ${appid} and object ID ${oid} is not authorized for this API endpoint`, 403)
|
||||
);
|
||||
}
|
||||
if (isAppApproved && approvedAppsToCreateRepos.includes(appid)) {
|
||||
scopes.push('createRepo');
|
||||
}
|
||||
if (isAppApproved && approvedAppsToReadLinks.includes(appid)) {
|
||||
scopes.push('links');
|
||||
}
|
||||
if (isAppApproved && approvedAppsToReadMaintainers.includes(appid)) {
|
||||
scopes.push('maintainers');
|
||||
}
|
||||
if (isAppApproved && approvedAppsToReadJitConfirms.includes(appid)) {
|
||||
scopes.push('jit/confirm');
|
||||
}
|
||||
const policyServiceScopeName = 'microsoft-github-policy-service';
|
||||
if (isAppApproved && approvedAppsToReadPolicyService.includes(appid)) {
|
||||
scopes.push(policyServiceScopeName);
|
||||
}
|
||||
if (isOidApproved && approvedOidsToCreateRepos.includes(oid)) {
|
||||
scopes.push('createRepo');
|
||||
}
|
||||
if (isOidApproved && approvedOidsToReadLinks.includes(oid)) {
|
||||
scopes.push('links');
|
||||
}
|
||||
if (isOidApproved && approvedOidsToReadJitConfirms.includes(oid)) {
|
||||
scopes.push('jit/confirm');
|
||||
}
|
||||
if (isOidApproved && approvedOidsToReadPolicyService.includes(appid)) {
|
||||
scopes.push(policyServiceScopeName);
|
||||
}
|
||||
|
||||
const apiToken = PersonalAccessToken.CreateFromAadAuthorization({
|
||||
appId: appid,
|
||||
oid,
|
||||
scopes: scopes.join(','),
|
||||
organizationScopes: '*',
|
||||
});
|
||||
const scopes = await aadApiValidator.getScopes(approvedAppMonikerId);
|
||||
const displayValues = await aadApiValidator.getDisplayValues(approvedAppMonikerId);
|
||||
|
||||
const apiToken = PersonalAccessToken.CreateFromAadAuthorization(
|
||||
{
|
||||
appId: appid,
|
||||
oid,
|
||||
scopes: scopes.join(','),
|
||||
organizationScopes: '*',
|
||||
},
|
||||
displayValues
|
||||
);
|
||||
req.apiKeyToken = apiToken;
|
||||
req.apiKeyProviderName = 'aad';
|
||||
insights?.trackEvent({
|
||||
|
|
|
@ -9,7 +9,12 @@ import Debug from 'debug';
|
|||
const debug = Debug.debug('user');
|
||||
|
||||
import { getProviders } from '../../transitional';
|
||||
import { ICorporateIdentity, IGitHubIdentity, IndividualContext, GitHubIdentitySource } from '../../user';
|
||||
import {
|
||||
ICorporateIdentity,
|
||||
IGitHubIdentity,
|
||||
IndividualContext,
|
||||
GitHubIdentitySource,
|
||||
} from '../../business/user';
|
||||
import { storeOriginalUrlAsReferrer } from '../../utils';
|
||||
import getCompanySpecificDeployment from '../companySpecificDeployment';
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import { ReposAppRequest } from '../../interfaces';
|
||||
import { getProviders } from '../../transitional';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { wrapError } from '../../utils';
|
||||
import { jsonError } from '../jsonError';
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { jsonError } from '..';
|
||||
import { IProviders, ReposAppRequest } from '../../interfaces';
|
||||
import { getProviders } from '../../transitional';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
|
||||
const cachedCorporateAliasRequestKey = '__corporateAlias';
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { jsonError } from '..';
|
|||
import { IProviders, ReposAppRequest } from '../../interfaces';
|
||||
import { IGraphEntry } from '../../lib/graphProvider';
|
||||
import { getProviders } from '../../transitional';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
|
||||
const cachedCorporateHierarchyRequestKey = '__corporateTree';
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { jsonError } from '..';
|
||||
import { IProviders, ReposAppRequest } from '../../interfaces';
|
||||
import { getProviders } from '../../transitional';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
|
||||
const cachedCorporateMailRequestKey = '__corporateMail';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
WebContext,
|
||||
SessionUserProperties,
|
||||
WebApiContext,
|
||||
} from '../../user';
|
||||
} from '../../business/user';
|
||||
import { getProviders } from '../../transitional';
|
||||
|
||||
export function webContextMiddleware(req, res, next) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { ErrorHelper, getProviders } from '../../transitional';
|
||||
import { Repository } from '../../business/repository';
|
||||
import { GitHubIdentitySource, IIndividualContextOptions, IndividualContext } from '../../user';
|
||||
import { GitHubIdentitySource, IIndividualContextOptions, IndividualContext } from '../../business/user';
|
||||
import getCompanySpecificDeployment from '../companySpecificDeployment';
|
||||
import {
|
||||
ReposAppRequest,
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
ReposAppRequest,
|
||||
} from '../../interfaces';
|
||||
import { getProviders } from '../../transitional';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import getCompanySpecificDeployment from '../companySpecificDeployment';
|
||||
|
||||
// --- team2 context
|
||||
|
|
|
@ -33,15 +33,18 @@ import routeLogger from './logger';
|
|||
import routeLocals from './locals';
|
||||
import routePassport from './passport-routes';
|
||||
|
||||
import { IProviders, SiteConfiguration } from '../interfaces';
|
||||
import routeApi from '../api';
|
||||
|
||||
import { IProviders, IReposApplication, SiteConfiguration } from '../interfaces';
|
||||
import { codespacesDevAssistant } from './codespaces';
|
||||
|
||||
export default async function initMiddleware(
|
||||
app,
|
||||
app: IReposApplication,
|
||||
express,
|
||||
config: SiteConfiguration,
|
||||
dirname,
|
||||
initializationError
|
||||
dirname: string,
|
||||
hasCustomRoutes: boolean,
|
||||
initializationError: Error
|
||||
) {
|
||||
config = config || ({} as SiteConfiguration);
|
||||
const appDirectory =
|
||||
|
@ -88,6 +91,9 @@ export default async function initMiddleware(
|
|||
app.enable('trust proxy');
|
||||
debug('proxy: trusting reverse proxy');
|
||||
}
|
||||
if (!hasCustomRoutes) {
|
||||
app.use('/api', routeApi);
|
||||
}
|
||||
if (applicationProfile.sessions) {
|
||||
app.use(await connectSession(app, config, providers));
|
||||
try {
|
||||
|
|
|
@ -339,6 +339,9 @@ export default async function initialize(
|
|||
if (!config || Object.getOwnPropertyNames(config).length === 0) {
|
||||
throw new Error('Empty configuration object');
|
||||
}
|
||||
if (!app.runtimeConfiguration) {
|
||||
app.runtimeConfiguration = {};
|
||||
}
|
||||
const applicationProfile =
|
||||
config?.web?.app && config.web.app !== 'repos'
|
||||
? await alternateRoutes(config, app, config.web.app)
|
||||
|
@ -453,14 +456,15 @@ export default async function initialize(
|
|||
exception = initializeError;
|
||||
}
|
||||
}
|
||||
const hasCustomRoutes = !!applicationProfile.customRoutes;
|
||||
try {
|
||||
await middlewareIndex(app, express, config, rootdir, exception);
|
||||
await middlewareIndex(app, express, config, rootdir, hasCustomRoutes, exception);
|
||||
} catch (middlewareError) {
|
||||
exception = middlewareError;
|
||||
}
|
||||
// ROUTES:
|
||||
if (!exception) {
|
||||
if (applicationProfile.customRoutes) {
|
||||
if (hasCustomRoutes) {
|
||||
await applicationProfile.customRoutes();
|
||||
} else {
|
||||
app.use('/', expressRoutes);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// Within the context, tries to resolve a link if it _can_. It does not force that a user is linked!
|
||||
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { getProviders } from '../../transitional';
|
||||
import { wrapError } from '../../utils';
|
||||
import { ReposAppRequest, IReposError } from '../../interfaces';
|
||||
|
|
|
@ -11,7 +11,9 @@ import createAADStrategy from './passport/aadStrategy';
|
|||
import createGithubStrategy from './passport/githubStrategy';
|
||||
import serializer from './passport/serializer';
|
||||
|
||||
export default function (app, config) {
|
||||
import type { IReposApplication, ReposAppRequest, SiteConfiguration } from '../interfaces';
|
||||
|
||||
export default function (app: IReposApplication, config: SiteConfiguration) {
|
||||
const supportedAuth = ['github', 'aad', 'oauth2'];
|
||||
|
||||
if (!supportedAuth.includes(config.authentication.scheme)) {
|
||||
|
@ -49,12 +51,12 @@ export default function (app, config) {
|
|||
}
|
||||
}
|
||||
|
||||
if (config.authentication.scheme == 'aad') {
|
||||
if (config.authentication.scheme === 'aad') {
|
||||
const aadStrategies = createAADStrategy(app, config);
|
||||
for (const name in aadStrategies) {
|
||||
passport.use(name, aadStrategies[name]);
|
||||
}
|
||||
} else if (config.authentication.scheme == 'oauth2') {
|
||||
} else if (config.authentication.scheme === 'oauth2') {
|
||||
// Set up oauth2 strategy here
|
||||
throw new Error('oauth2 is not currently implemented');
|
||||
}
|
||||
|
@ -71,15 +73,9 @@ export default function (app, config) {
|
|||
passport.deserializeUser(serializer.deserialize(serializerOptions));
|
||||
serializer.initialize(serializerOptions, app);
|
||||
|
||||
app.use((req, res, next) => {
|
||||
if (
|
||||
req.insights &&
|
||||
req.insights.properties &&
|
||||
config.authentication.scheme === 'aad' &&
|
||||
req.user &&
|
||||
req.user.azure
|
||||
) {
|
||||
req.insights.properties.aadId = req.user.azure.oid;
|
||||
app.use((req: ReposAppRequest, res, next) => {
|
||||
if (req?.insights?.commonProperties && config.authentication.scheme === 'aad' && req?.user?.azure?.oid) {
|
||||
req.insights.commonProperties.aadId = req.user.azure.oid;
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ import appPackage from '../package.json';
|
|||
import { getStaticBlobCacheFallback } from '../lib/staticBlobCacheFallback';
|
||||
import { getProviders, splitSemiColonCommas } from '../transitional';
|
||||
import { ReposAppRequest } from '../interfaces';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
|
||||
const staticReactPackageNameKey = 'static-react-package-name';
|
||||
const staticClientPackageName = appPackage[staticReactPackageNameKey];
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
import { CreateError, hasStaticReactClientApp } from '../transitional';
|
||||
import { hasStaticReactClientApp } from '../transitional';
|
||||
|
||||
import appPackage from '../package.json';
|
||||
import { ReposAppRequest } from '../interfaces';
|
||||
|
||||
import type { IReposApplication, SiteConfiguration } from '../interfaces';
|
||||
|
||||
const packageVariableName = 'static-react-package-name';
|
||||
const otherPackageVariableName = 'static-client-package-name';
|
||||
|
@ -17,7 +18,23 @@ const staticClientFlightingPackageName = appPackage[staticReactFlightingPackageN
|
|||
import Debug from 'debug';
|
||||
const debug = Debug.debug('startup');
|
||||
|
||||
export function StaticReactClientApp(app, express, config: any) {
|
||||
export type RuntimeConfigurationClient = {
|
||||
packageName?: string;
|
||||
packageVersion?: string;
|
||||
flighting?: {
|
||||
packageName: string;
|
||||
packageVersion: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type RootRuntimeConfigurationClient = {
|
||||
client?: RuntimeConfigurationClient;
|
||||
};
|
||||
|
||||
export function StaticReactClientApp(app: IReposApplication, express, config: SiteConfiguration) {
|
||||
const clientRuntimeConfiguration: RuntimeConfigurationClient = {};
|
||||
app.runtimeConfiguration.client = clientRuntimeConfiguration;
|
||||
|
||||
// Serve/host the static client app from the location reported by the private
|
||||
// NPM module for the React app. Assumes that the inclusion of the package
|
||||
// returns the path to host.
|
||||
|
@ -39,6 +56,8 @@ export function StaticReactClientApp(app, express, config: any) {
|
|||
const clientPackage = require(`${staticClientPackageName}/package.json`);
|
||||
debug(`Hosting React client version ${clientPackage.version} from ${clientDistPath}`);
|
||||
app.use('/', express.static(clientDistPath));
|
||||
clientRuntimeConfiguration.packageName = staticClientPackageName;
|
||||
clientRuntimeConfiguration.packageVersion = clientPackage.version;
|
||||
} catch (hostClientError) {
|
||||
console.error(`The React client could not be loaded via package ${staticClientPackageName}`);
|
||||
throw hostClientError;
|
||||
|
@ -56,6 +75,10 @@ export function StaticReactClientApp(app, express, config: any) {
|
|||
const clientPackage = require(`${staticClientFlightingPackageName}/package.json`);
|
||||
debug(`Hosting flighting React client version ${clientPackage.version} from ${clientDistPath}`);
|
||||
app.use('/', express.static(clientDistPath));
|
||||
clientRuntimeConfiguration.flighting = {
|
||||
packageName: staticClientFlightingPackageName,
|
||||
packageVersion: clientPackage.version,
|
||||
};
|
||||
} catch (hostClientError) {
|
||||
console.error(`The flighting React client could not be loaded via package ${staticClientPackageName}`);
|
||||
throw hostClientError;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"dependencies": {
|
||||
"@azure/cosmos": "3.17.3",
|
||||
"@azure/data-tables": "13.2.2",
|
||||
"@azure/identity": "3.1.4",
|
||||
"@azure/identity": "3.2.0",
|
||||
"@azure/keyvault-secrets": "4.7.0",
|
||||
"@azure/service-bus": "7.9.0",
|
||||
"@azure/storage-blob": "12.14.0",
|
||||
|
@ -50,7 +50,7 @@
|
|||
"moment": "2.29.4",
|
||||
"morgan": "1.10.0",
|
||||
"node-jose": "2.2.0",
|
||||
"nodemailer": "6.9.1",
|
||||
"nodemailer": "6.9.2",
|
||||
"object-path": "0.11.8",
|
||||
"octicons": "5.0.1",
|
||||
"passport": "0.6.0",
|
||||
|
@ -80,7 +80,7 @@
|
|||
"@types/luxon": "3.3.0",
|
||||
"@types/memory-cache": "0.2.2",
|
||||
"@types/morgan": "1.9.4",
|
||||
"@types/node": "18.16.3",
|
||||
"@types/node": "20.1.2",
|
||||
"@types/node-jose": "1.1.10",
|
||||
"@types/object-path": "0.11.1",
|
||||
"@types/passport": "1.0.12",
|
||||
|
@ -89,13 +89,13 @@
|
|||
"@types/pg": "8.6.6",
|
||||
"@types/pug": "2.0.6",
|
||||
"@types/recursive-readdir": "2.2.1",
|
||||
"@types/semver": "7.3.13",
|
||||
"@types/semver": "7.5.0",
|
||||
"@types/simple-oauth2": "5.0.4",
|
||||
"@types/validator": "13.7.15",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.2",
|
||||
"@typescript-eslint/parser": "5.59.2",
|
||||
"@types/validator": "13.7.17",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.5",
|
||||
"@typescript-eslint/parser": "5.59.5",
|
||||
"cspell": "6.31.1",
|
||||
"eslint": "8.39.0",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-n": "15.7.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
|
@ -359,9 +359,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@azure/identity": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@azure/identity/-/identity-3.1.4.tgz",
|
||||
"integrity": "sha512-USvxmO6p7dFEcz1e0Kq/WQY6YbvX8hOeIibxxLBQC4Pxl4QK+DL72agZ9e5RYZc55QjC7Ja6q1+mQaXfmbrLhA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/identity/-/identity-3.2.0.tgz",
|
||||
"integrity": "sha512-WgJRnIweTUJn+h34xomlgbG5/5pwoQ0aBA5gbUtZPFx/UDKsrIZylI+uH++OjLkgyjT4FzLfms048+t+goUo6g==",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^1.0.0",
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
|
@ -1566,14 +1566,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz",
|
||||
"integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
|
||||
"integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.5.1",
|
||||
"espree": "^9.5.2",
|
||||
"globals": "^13.19.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
|
@ -1589,9 +1589,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz",
|
||||
"integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==",
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz",
|
||||
"integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -2871,9 +2871,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
|
||||
"integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q=="
|
||||
"version": "20.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.2.tgz",
|
||||
"integrity": "sha512-CTO/wa8x+rZU626cL2BlbCDzydgnFNgc19h4YvizpTO88MFQxab8wqisxaofQJ/9bLGugRdWIuX/TbIs6VVF6g=="
|
||||
},
|
||||
"node_modules/@types/node-fetch": {
|
||||
"version": "2.6.2",
|
||||
|
@ -3005,9 +3005,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
|
||||
"integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/serve-static": {
|
||||
|
@ -3040,9 +3040,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/validator": {
|
||||
"version": "13.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.15.tgz",
|
||||
"integrity": "sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ==",
|
||||
"version": "13.7.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz",
|
||||
"integrity": "sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
|
@ -3061,15 +3061,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz",
|
||||
"integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz",
|
||||
"integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.59.2",
|
||||
"@typescript-eslint/type-utils": "5.59.2",
|
||||
"@typescript-eslint/utils": "5.59.2",
|
||||
"@typescript-eslint/scope-manager": "5.59.5",
|
||||
"@typescript-eslint/type-utils": "5.59.5",
|
||||
"@typescript-eslint/utils": "5.59.5",
|
||||
"debug": "^4.3.4",
|
||||
"grapheme-splitter": "^1.0.4",
|
||||
"ignore": "^5.2.0",
|
||||
|
@ -3095,14 +3095,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz",
|
||||
"integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz",
|
||||
"integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/typescript-estree": "5.59.2",
|
||||
"@typescript-eslint/scope-manager": "5.59.5",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/typescript-estree": "5.59.5",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -3122,13 +3122,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz",
|
||||
"integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz",
|
||||
"integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/visitor-keys": "5.59.2"
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/visitor-keys": "5.59.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -3139,13 +3139,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz",
|
||||
"integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz",
|
||||
"integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "5.59.2",
|
||||
"@typescript-eslint/utils": "5.59.2",
|
||||
"@typescript-eslint/typescript-estree": "5.59.5",
|
||||
"@typescript-eslint/utils": "5.59.5",
|
||||
"debug": "^4.3.4",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
|
@ -3166,9 +3166,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz",
|
||||
"integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz",
|
||||
"integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -3179,13 +3179,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz",
|
||||
"integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz",
|
||||
"integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/visitor-keys": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/visitor-keys": "5.59.5",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
|
@ -3206,17 +3206,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz",
|
||||
"integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz",
|
||||
"integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@types/semver": "^7.3.12",
|
||||
"@typescript-eslint/scope-manager": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/typescript-estree": "5.59.2",
|
||||
"@typescript-eslint/scope-manager": "5.59.5",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/typescript-estree": "5.59.5",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"semver": "^7.3.7"
|
||||
},
|
||||
|
@ -3232,12 +3232,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz",
|
||||
"integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz",
|
||||
"integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -4886,15 +4886,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz",
|
||||
"integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==",
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz",
|
||||
"integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.0.2",
|
||||
"@eslint/js": "8.39.0",
|
||||
"@eslint/eslintrc": "^2.0.3",
|
||||
"@eslint/js": "8.40.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
|
@ -4905,8 +4905,8 @@
|
|||
"doctrine": "^3.0.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^7.2.0",
|
||||
"eslint-visitor-keys": "^3.4.0",
|
||||
"espree": "^9.5.1",
|
||||
"eslint-visitor-keys": "^3.4.1",
|
||||
"espree": "^9.5.2",
|
||||
"esquery": "^1.4.2",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -5084,9 +5084,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
|
||||
"integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
|
||||
"integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -5121,14 +5121,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz",
|
||||
"integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==",
|
||||
"version": "9.5.2",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
|
||||
"integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.8.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^3.4.0"
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -8297,9 +8297,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/nodemailer": {
|
||||
"version": "6.9.1",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz",
|
||||
"integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==",
|
||||
"version": "6.9.2",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.2.tgz",
|
||||
"integrity": "sha512-4+TYaa/e1nIxQfyw/WzNPYTEZ5OvHIDEnmjs4LPmIfccPQN+2CYKmGHjWixn/chzD3bmUTu5FMfpltizMxqzdg==",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
|
@ -10854,9 +10854,9 @@
|
|||
}
|
||||
},
|
||||
"@azure/identity": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@azure/identity/-/identity-3.1.4.tgz",
|
||||
"integrity": "sha512-USvxmO6p7dFEcz1e0Kq/WQY6YbvX8hOeIibxxLBQC4Pxl4QK+DL72agZ9e5RYZc55QjC7Ja6q1+mQaXfmbrLhA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/identity/-/identity-3.2.0.tgz",
|
||||
"integrity": "sha512-WgJRnIweTUJn+h34xomlgbG5/5pwoQ0aBA5gbUtZPFx/UDKsrIZylI+uH++OjLkgyjT4FzLfms048+t+goUo6g==",
|
||||
"requires": {
|
||||
"@azure/abort-controller": "^1.0.0",
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
|
@ -11857,14 +11857,14 @@
|
|||
"dev": true
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz",
|
||||
"integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
|
||||
"integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.5.1",
|
||||
"espree": "^9.5.2",
|
||||
"globals": "^13.19.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
|
@ -11874,9 +11874,9 @@
|
|||
}
|
||||
},
|
||||
"@eslint/js": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz",
|
||||
"integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==",
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz",
|
||||
"integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/boom": {
|
||||
|
@ -12960,9 +12960,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
|
||||
"integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q=="
|
||||
"version": "20.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.2.tgz",
|
||||
"integrity": "sha512-CTO/wa8x+rZU626cL2BlbCDzydgnFNgc19h4YvizpTO88MFQxab8wqisxaofQJ/9bLGugRdWIuX/TbIs6VVF6g=="
|
||||
},
|
||||
"@types/node-fetch": {
|
||||
"version": "2.6.2",
|
||||
|
@ -13093,9 +13093,9 @@
|
|||
}
|
||||
},
|
||||
"@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
|
||||
"integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/serve-static": {
|
||||
|
@ -13128,9 +13128,9 @@
|
|||
}
|
||||
},
|
||||
"@types/validator": {
|
||||
"version": "13.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.15.tgz",
|
||||
"integrity": "sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ==",
|
||||
"version": "13.7.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz",
|
||||
"integrity": "sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yargs": {
|
||||
|
@ -13149,15 +13149,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz",
|
||||
"integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz",
|
||||
"integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.59.2",
|
||||
"@typescript-eslint/type-utils": "5.59.2",
|
||||
"@typescript-eslint/utils": "5.59.2",
|
||||
"@typescript-eslint/scope-manager": "5.59.5",
|
||||
"@typescript-eslint/type-utils": "5.59.5",
|
||||
"@typescript-eslint/utils": "5.59.5",
|
||||
"debug": "^4.3.4",
|
||||
"grapheme-splitter": "^1.0.4",
|
||||
"ignore": "^5.2.0",
|
||||
|
@ -13167,53 +13167,53 @@
|
|||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz",
|
||||
"integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz",
|
||||
"integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/typescript-estree": "5.59.2",
|
||||
"@typescript-eslint/scope-manager": "5.59.5",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/typescript-estree": "5.59.5",
|
||||
"debug": "^4.3.4"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz",
|
||||
"integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz",
|
||||
"integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/visitor-keys": "5.59.2"
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/visitor-keys": "5.59.5"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/type-utils": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz",
|
||||
"integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz",
|
||||
"integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/typescript-estree": "5.59.2",
|
||||
"@typescript-eslint/utils": "5.59.2",
|
||||
"@typescript-eslint/typescript-estree": "5.59.5",
|
||||
"@typescript-eslint/utils": "5.59.5",
|
||||
"debug": "^4.3.4",
|
||||
"tsutils": "^3.21.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz",
|
||||
"integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz",
|
||||
"integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz",
|
||||
"integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz",
|
||||
"integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/visitor-keys": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/visitor-keys": "5.59.5",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
|
@ -13222,28 +13222,28 @@
|
|||
}
|
||||
},
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz",
|
||||
"integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz",
|
||||
"integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@types/semver": "^7.3.12",
|
||||
"@typescript-eslint/scope-manager": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/typescript-estree": "5.59.2",
|
||||
"@typescript-eslint/scope-manager": "5.59.5",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"@typescript-eslint/typescript-estree": "5.59.5",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"semver": "^7.3.7"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "5.59.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz",
|
||||
"integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==",
|
||||
"version": "5.59.5",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz",
|
||||
"integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.59.2",
|
||||
"@typescript-eslint/types": "5.59.5",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
}
|
||||
},
|
||||
|
@ -14476,15 +14476,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz",
|
||||
"integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==",
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz",
|
||||
"integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.0.2",
|
||||
"@eslint/js": "8.39.0",
|
||||
"@eslint/eslintrc": "^2.0.3",
|
||||
"@eslint/js": "8.40.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
|
@ -14495,8 +14495,8 @@
|
|||
"doctrine": "^3.0.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^7.2.0",
|
||||
"eslint-visitor-keys": "^3.4.0",
|
||||
"espree": "^9.5.1",
|
||||
"eslint-visitor-keys": "^3.4.1",
|
||||
"espree": "^9.5.2",
|
||||
"esquery": "^1.4.2",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -14628,20 +14628,20 @@
|
|||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
|
||||
"integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
|
||||
"integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz",
|
||||
"integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==",
|
||||
"version": "9.5.2",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
|
||||
"integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^8.8.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^3.4.0"
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
|
@ -16997,9 +16997,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"nodemailer": {
|
||||
"version": "6.9.1",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz",
|
||||
"integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA=="
|
||||
"version": "6.9.2",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.2.tgz",
|
||||
"integrity": "sha512-4+TYaa/e1nIxQfyw/WzNPYTEZ5OvHIDEnmjs4LPmIfccPQN+2CYKmGHjWixn/chzD3bmUTu5FMfpltizMxqzdg=="
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
|
|
16
package.json
16
package.json
|
@ -66,7 +66,7 @@
|
|||
"dependencies": {
|
||||
"@azure/cosmos": "3.17.3",
|
||||
"@azure/data-tables": "13.2.2",
|
||||
"@azure/identity": "3.1.4",
|
||||
"@azure/identity": "3.2.0",
|
||||
"@azure/keyvault-secrets": "4.7.0",
|
||||
"@azure/service-bus": "7.9.0",
|
||||
"@azure/storage-blob": "12.14.0",
|
||||
|
@ -105,7 +105,7 @@
|
|||
"moment": "2.29.4",
|
||||
"morgan": "1.10.0",
|
||||
"node-jose": "2.2.0",
|
||||
"nodemailer": "6.9.1",
|
||||
"nodemailer": "6.9.2",
|
||||
"object-path": "0.11.8",
|
||||
"octicons": "5.0.1",
|
||||
"passport": "0.6.0",
|
||||
|
@ -135,7 +135,7 @@
|
|||
"@types/luxon": "3.3.0",
|
||||
"@types/memory-cache": "0.2.2",
|
||||
"@types/morgan": "1.9.4",
|
||||
"@types/node": "18.16.3",
|
||||
"@types/node": "20.1.2",
|
||||
"@types/node-jose": "1.1.10",
|
||||
"@types/object-path": "0.11.1",
|
||||
"@types/passport": "1.0.12",
|
||||
|
@ -144,13 +144,13 @@
|
|||
"@types/pg": "8.6.6",
|
||||
"@types/pug": "2.0.6",
|
||||
"@types/recursive-readdir": "2.2.1",
|
||||
"@types/semver": "7.3.13",
|
||||
"@types/semver": "7.5.0",
|
||||
"@types/simple-oauth2": "5.0.4",
|
||||
"@types/validator": "13.7.15",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.2",
|
||||
"@typescript-eslint/parser": "5.59.2",
|
||||
"@types/validator": "13.7.17",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.5",
|
||||
"@typescript-eslint/parser": "5.59.5",
|
||||
"cspell": "6.31.1",
|
||||
"eslint": "8.39.0",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-n": "15.7.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
IBasicGitHubAppInstallation,
|
||||
SpecialTeam,
|
||||
} from '../../entities/organizationSettings/organizationSetting';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { Operations, Organization } from '../../business';
|
||||
import GitHubApplication from '../../business/application';
|
||||
import {
|
||||
|
|
|
@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler';
|
|||
const router: Router = Router();
|
||||
|
||||
import { CreateError, hasStaticReactClientApp, getProviders } from '../transitional';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
import { storeOriginalUrlAsVariable } from '../utils';
|
||||
import { AuthorizeOnlyCorporateAdministrators } from '../middleware/business/corporateAdministrators';
|
||||
|
||||
|
|
|
@ -8,11 +8,7 @@ const router: Router = Router();
|
|||
|
||||
import { webContextMiddleware } from '../middleware/business/setContext';
|
||||
|
||||
import ApiRoute from '../api';
|
||||
|
||||
router.use('/api', ApiRoute);
|
||||
|
||||
router.use(webContextMiddleware);
|
||||
import clientApiRoute from '../api/client';
|
||||
|
||||
import ThanksRoute from './thanks';
|
||||
import MyInfoRoute from './diagnostics';
|
||||
|
@ -20,12 +16,16 @@ import ExploreRoute from './explore';
|
|||
import ApprovalsRoute from './approvals';
|
||||
import AuthenticatedRoute from './index-authenticated';
|
||||
|
||||
router.use('/thanks', ThanksRoute);
|
||||
router.use('/myinfo', MyInfoRoute);
|
||||
|
||||
import { hasStaticReactClientApp } from '../transitional';
|
||||
import { injectReactClient } from '../middleware';
|
||||
|
||||
router.use('/api/client', clientApiRoute);
|
||||
|
||||
router.use(webContextMiddleware);
|
||||
|
||||
router.use('/thanks', ThanksRoute);
|
||||
router.use('/myinfo', MyInfoRoute);
|
||||
|
||||
const hasReactApp = hasStaticReactClientApp();
|
||||
const reactRoute = hasReactApp ? injectReactClient() : undefined;
|
||||
router.use('/approvals', reactRoute || ApprovalsRoute); // redirects into settings for site users
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
LinkOperationSource,
|
||||
} from '../interfaces';
|
||||
import { getProviders, splitSemiColonCommas } from '../transitional';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
import { isCodespacesAuthenticating, storeOriginalUrlAsReferrer, wrapError } from '../utils';
|
||||
|
||||
import validator from 'validator';
|
||||
|
|
|
@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler';
|
|||
const router: Router = Router();
|
||||
|
||||
import { getProviders } from '../../transitional';
|
||||
import { IAggregateUserSummary } from '../../user/aggregate';
|
||||
import { IAggregateUserSummary } from '../../business/user/aggregate';
|
||||
import { TeamJoinApprovalEntity } from '../../entities/teamJoinApproval/teamJoinApproval';
|
||||
import { Team } from '../../business';
|
||||
import { ReposAppRequest, OrganizationMembershipState } from '../../interfaces';
|
||||
|
|
|
@ -12,7 +12,7 @@ const router: Router = Router();
|
|||
import querystring from 'querystring';
|
||||
|
||||
import { CreateError, getProviders } from '../../transitional';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
import { sleep, storeOriginalUrlAsReferrer, wrapError } from '../../utils';
|
||||
import RequireActiveGitHubSession from '../../middleware/github/requireActiveSession';
|
||||
import { jsonError } from '../../middleware/jsonError';
|
||||
|
|
|
@ -16,7 +16,7 @@ import routeAdministrativeLock from './repoAdministrativeLock';
|
|||
import NewRepositoryLockdownSystem from '../../features/newRepositories/newRepositoryLockdown';
|
||||
import { IGraphEntry } from '../../lib/graphProvider';
|
||||
import { IMail } from '../../lib/mailProvider';
|
||||
import { IndividualContext } from '../../user';
|
||||
import { IndividualContext } from '../../business/user';
|
||||
|
||||
import { Repository, Collaborator, TeamPermission, Organization, OrganizationMember } from '../../business';
|
||||
import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata';
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ErrorHelper, getProviders } from '../../../../transitional';
|
|||
import { Team } from '../../../../business';
|
||||
import { PermissionWorkflowEngine } from '../approvals';
|
||||
import RenderHtmlMail from '../../../../lib/emailRender';
|
||||
import { IndividualContext } from '../../../../user';
|
||||
import { IndividualContext } from '../../../../business/user';
|
||||
import { ReposAppRequest, UserAlertType, IProviders } from '../../../../interfaces';
|
||||
|
||||
interface ILocalRequest extends ReposAppRequest {
|
||||
|
|
|
@ -24,7 +24,7 @@ import lowercaser from '../../../middleware/lowercaser';
|
|||
|
||||
import RouteMaintainer from './index-maintainer';
|
||||
import { Operations, Organization, Repository, Team, TeamMember } from '../../../business';
|
||||
import { IndividualContext } from '../../../user';
|
||||
import { IndividualContext } from '../../../business/user';
|
||||
import {
|
||||
ReposAppRequest,
|
||||
GitHubTeamRole,
|
||||
|
|
|
@ -21,7 +21,7 @@ import QueryCache from '../business/queryCache';
|
|||
import { GitHubRepositoryType, IReposAppWithTeam } from '../interfaces';
|
||||
import { IRequestTeamPermissions } from '../middleware/github/teamPermissions';
|
||||
import { getProviders } from '../transitional';
|
||||
import { UserContext } from '../user/aggregate';
|
||||
import { UserContext } from '../business/user/aggregate';
|
||||
|
||||
interface IGetReposAndOptionalTeamPermissionsResponse {
|
||||
reposData: Repository[];
|
||||
|
|
|
@ -13,7 +13,7 @@ import { safeLocalRedirectUrl } from '../../utils';
|
|||
import { Operations } from '../../business';
|
||||
import { Team } from '../../business';
|
||||
import { Organization } from '../../business';
|
||||
import { IAggregateUserTeams } from '../../user/aggregate';
|
||||
import { IAggregateUserTeams } from '../../business/user/aggregate';
|
||||
import { ReposAppRequest, IReposError, UserAlertType } from '../../interfaces';
|
||||
import { getProviders } from '../../transitional';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { NextFunction, Response } from 'express';
|
|||
import { getProviders } from '../transitional';
|
||||
import { Operations } from '../business';
|
||||
import { Team } from '../business';
|
||||
import { UserContext } from '../user/aggregate';
|
||||
import { UserContext } from '../business/user/aggregate';
|
||||
|
||||
import TeamSearch from '../business/teamSearch';
|
||||
import { ICrossOrganizationMembershipByOrganization, ReposAppRequest } from '../interfaces';
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ErrorHelper, getProviders } from '../transitional';
|
|||
import { AuditLogRecord } from '../entities/auditLogRecord/auditLogRecord';
|
||||
import { daysInMilliseconds } from '../utils';
|
||||
import { AuditEvents } from '../entities/auditLogRecord';
|
||||
import { IGitHubIdentity, IndividualContext } from '../user';
|
||||
import { IGitHubIdentity, IndividualContext } from '../business/user';
|
||||
import { IMail } from '../lib/mailProvider';
|
||||
import { GitHubRepositoryPermission, ReposAppRequest, UserAlertType } from '../interfaces';
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const router: Router = Router();
|
|||
|
||||
import { getProviders } from '../transitional';
|
||||
import { wrapError } from '../utils';
|
||||
import { IndividualContext } from '../user';
|
||||
import { IndividualContext } from '../business/user';
|
||||
import { jsonError } from '../middleware';
|
||||
import { ReposAppRequest, OrganizationMembershipState, UnlinkPurpose } from '../interfaces';
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ export class CreateError {
|
|||
return error;
|
||||
}
|
||||
|
||||
static NotFound(message: string, innerError?: Error): Error {
|
||||
static NotFound(message?: string, innerError?: Error): Error {
|
||||
return ErrorHelper.SetInnerError(CreateError.CreateStatusCodeError(404, message), innerError);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
"./data/**/*",
|
||||
"./entities/**/*",
|
||||
"./features/**/*",
|
||||
"./github/**/*",
|
||||
"./interfaces/**/*",
|
||||
"./jobs/**/*",
|
||||
"./lib/**/*",
|
||||
|
@ -33,7 +32,6 @@
|
|||
"./routes/**/*",
|
||||
"./scripts/**/*",
|
||||
"./test/**/*",
|
||||
"./user/**/*",
|
||||
"./webhooks/**/*"
|
||||
]
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче