зеркало из
1
0
Форкнуть 0

Refactor provider instance get

For improved type safety, this uses a function to return the
IProviders instance from the Express app, replacing all instances
of using req.app.settings.providers as IProviders, etc.

This may also make everything slightly more testable, eventually.
This commit is contained in:
Jeff Wilcox 2021-03-19 09:20:39 -07:00
Родитель e6ea0608c8
Коммит b3ccbac546
84 изменённых файлов: 408 добавлений и 492 удалений

Просмотреть файл

@ -5,15 +5,15 @@
import express from 'express';
import { jsonError } from '../../middleware/jsonError';
import { IProviders, ReposAppRequest } from '../../transitional';
import { jsonError } from '../../middleware';
import { getProviders, ReposAppRequest } from '../../transitional';
const router = express.Router();
// TODO: move to modern w/administration experience, optionally
router.get('/', (req: ReposAppRequest, res, next) => {
const { config } = req.app.settings.providers as IProviders;
const { config } = getProviders(req);
const text = config?.serviceMessage?.banner || null;
const link = config.serviceMessage?.link;
const details = config.serviceMessage?.details;

Просмотреть файл

@ -10,7 +10,7 @@ import { TeamJsonFormat, Team, Organization } from '../../../business';
import { TeamJoinApprovalEntity } from '../../../entities/teamJoinApproval/teamJoinApproval';
import { jsonError } from '../../../middleware';
import { ApprovalPair, Approvals_getTeamMaintainerApprovals, Approvals_getUserRequests, closeOldRequest } from '../../../routes/settings/approvals';
import { ReposAppRequest, IProviders } from '../../../transitional';
import { ReposAppRequest, getProviders } from '../../../transitional';
import { IndividualContext } from '../../../user';
const router = express.Router();
@ -23,7 +23,7 @@ const approvalPairToJson = (pair: ApprovalPair) => {
};
router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { approvalProvider, operations } = req.app.settings.providers as IProviders;
const { approvalProvider, operations } = getProviders(req);
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
if (!activeContext.link) {
return res.json({
@ -56,7 +56,7 @@ router.get('/:approvalId', asyncHandler(async (req: ReposAppRequest, res, next)
if (!activeContext.link) {
return res.json({});
}
const { approvalProvider, operations } = req.app.settings.providers as IProviders;
const { approvalProvider, operations } = getProviders(req);
const corporateId = activeContext.corporateIdentity.id;
let request: TeamJoinApprovalEntity = null;
try {

Просмотреть файл

@ -10,7 +10,7 @@ import { Organization } from '../../../business';
import { jsonError } from '../../../middleware';
import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment';
import { ErrorHelper, IProviders, ReposAppRequest } from '../../../transitional';
import { ErrorHelper, getProviders, IProviders, ReposAppRequest } from '../../../transitional';
import { IndividualContext } from '../../../user';
import RouteApprovals from './approvals';
@ -27,7 +27,7 @@ deployment?.routes?.api?.context?.index && deployment?.routes?.api?.context?.ind
router.use('/approvals', RouteApprovals);
router.get('/', (req: ReposAppRequest, res) => {
const { config } = req.app.settings.providers as IProviders;
const { config } = getProviders(req);
const { continuousDeployment } = config;
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const isGitHubAuthenticated = !!activeContext.getSessionBasedGitHubIdentity()?.id;
@ -43,7 +43,7 @@ router.get('/', (req: ReposAppRequest, res) => {
});
router.get('/accountDetails', asyncHandler(async (req: ReposAppRequest, res) => {
const { operations} = req.app.settings.providers as IProviders;
const { operations} = getProviders(req);
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const gh = activeContext.getGitHubIdentity();
if (!gh || !gh.id) {
@ -63,7 +63,7 @@ router.get('/teams', RouteTeams);
router.use('/orgs/:orgName', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { orgName } = req.params;
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
// const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
// if (!activeContext.link) {
// return next(jsonError('Account is not linked', 400));

Просмотреть файл

@ -5,6 +5,7 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { ITeamMembershipRoleState, OrganizationMembershipState } from '../../../../business';
import { TeamJoinApprovalEntity } from '../../../../entities/teamJoinApproval/teamJoinApproval';
import { jsonError } from '../../../../middleware';
@ -12,7 +13,7 @@ import { AddTeamMembershipToRequest, AddTeamPermissionsToRequest, getContextualT
import { submitTeamJoinRequest } from '../../../../routes/org/team';
import { postActionDecision, TeamApprovalDecision } from '../../../../routes/org/team/approval';
import { PermissionWorkflowEngine } from '../../../../routes/org/team/approvals';
import { IProviders, ReposAppRequest } from '../../../../transitional';
import { getProviders, ReposAppRequest } from '../../../../transitional';
import { IndividualContext } from '../../../../user';
const router = express.Router();
@ -37,7 +38,7 @@ router.get('/permissions',
);
router.get('/join/request', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { approvalProvider } = req.app.settings.providers as IProviders;
const { approvalProvider } = getProviders(req);
const team = getContextualTeam(req);
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
let request: TeamJoinApprovalEntity = null;
@ -55,7 +56,7 @@ router.post('/join',
asyncHandler(AddTeamMembershipToRequest),
asyncHandler(async (req: ReposAppRequest, res, next) => {
try {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { approvalProvider } = providers;
const membership = getTeamMembershipFromRequest(req);
if (!membership.isLinked) {
@ -95,7 +96,7 @@ router.post('/join/approvals/:approvalId',
if (!permissions.allowAdministration) {
return next(jsonError('you do not have permission to administer this team', 401));
}
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { approvalProvider, operations } = providers;
const team = getContextualTeam(req);
const request = await approvalProvider.getApprovalEntity(id);
@ -145,7 +146,7 @@ router.get('/join/approvals/:approvalId',
if (!permissions.allowAdministration) {
return next(jsonError('you do not have permission to administer this team', 401));
}
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { approvalProvider, operations } = providers;
const team = getContextualTeam(req);
const request = await approvalProvider.getApprovalEntity(id);
@ -158,7 +159,7 @@ router.get('/join/approvals/:approvalId',
router.get('/join/approvals',
asyncHandler(AddTeamPermissionsToRequest),
asyncHandler(async (req: ReposAppRequest, res, next) => {
const { approvalProvider } = req.app.settings.providers as IProviders;
const { approvalProvider } = getProviders(req);
const team = getContextualTeam(req);
const permissions = getTeamPermissionsFromRequest(req);
let response: ITeamApprovalsJsonResponse = {

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
import { apiContextMiddleware, AddLinkToRequest, requireAccessTokenClient, setIdentity, jsonError } from '../../middleware';
import { IProviders, ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment';
@ -25,7 +25,7 @@ import RouteCrossOrganizationTeams from './teams';
const router = express.Router();
router.use((req: ReposAppRequest, res, next) => {
const { config } = req.app.settings.providers as IProviders;
const { config } = getProviders(req);
if (config?.features?.allowApiClient) {
return req.isAuthenticated() ? next() : next(jsonError('Session is not authenticated', 401));
}

Просмотреть файл

@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler';
import { IndividualContext } from '../../user';
import { jsonError } from '../../middleware';
import { IProviders, ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import { unlinkInteractive } from '../../routes/unlink';
import { interactiveLinkUser } from '../../routes/link';
@ -16,7 +16,7 @@ const router = express.Router();
async function validateLinkOk(req: ReposAppRequest, res, next) {
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const insights = providers.insights;
const config = providers.config;
let validateAndBlockGuests = false;

Просмотреть файл

@ -9,7 +9,7 @@ const router = express.Router();
import _ from 'lodash';
import { ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, IProviders, getProviders } from '../../transitional';
import { jsonError } from '../../middleware/jsonError';
import { IndividualContext } from '../../user';
import { Organization } from '../../business/organization';
@ -66,7 +66,7 @@ router.get('/personalizedTeams', asyncHandler(async (req: ILocalApiRequest, res,
}));
router.get('/teams', asyncHandler(async (req: ILocalApiRequest, res, next) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const queryCache = providers.queryCache;
const organization = req.organization as Organization;
const broadTeams = new Set(organization.broadAccessTeams);
@ -119,6 +119,7 @@ router.get('/teams', asyncHandler(async (req: ILocalApiRequest, res, next) => {
}));
router.get('/repo/:repo', asyncHandler(async (req: ILocalApiRequest, res) => {
const { insights } = getProviders(req);
const repoName = req.params.repo;
let error = null;
try {
@ -128,7 +129,7 @@ router.get('/repo/:repo', asyncHandler(async (req: ILocalApiRequest, res) => {
res.status(404).end();
error = repoDetailsError;
}
req.app.settings.providers.insights.trackEvent({
insights?.trackEvent({
name: 'ApiClientNewRepoValidateAvailability',
properties: {
found: error ? true : false,
@ -140,7 +141,7 @@ router.get('/repo/:repo', asyncHandler(async (req: ILocalApiRequest, res) => {
export async function discoverUserIdentities(req: ReposAppRequest, res, next) {
const apiContext = req.apiContext as IndividualContext;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const mailAddressProvider = providers.mailAddressProvider;
// Try and also learn if we know their e-mail address to send the new repo mail to
const upn = apiContext.corporateIdentity.username;
@ -160,10 +161,10 @@ export async function discoverUserIdentities(req: ReposAppRequest, res, next) {
router.post('/repo/:repo', asyncHandler(discoverUserIdentities), asyncHandler(createRepositoryFromClient));
export async function createRepositoryFromClient(req: ILocalApiRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { insights, diagnosticsDrop, customizedNewRepositoryLogic } = providers;
const individualContext = req.individualContext || req.apiContext;
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
const organization = req.organization as Organization;
const existingRepoId = req.body.existingrepoid;
const correlationId = req.correlationId;

Просмотреть файл

@ -4,7 +4,7 @@
//
import express from 'express';
import { ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import { jsonError } from '../../middleware/jsonError';
import newOrgRepo from './newOrgRepo';
@ -12,7 +12,7 @@ const router = express.Router();
router.use('/org/:org', (req: ReposAppRequest, res, next) => {
const orgName = req.params.org;
const operations = req.app.settings.providers.operations;
const { operations } = getProviders(req);
try {
req.organization = operations.getOrganization(orgName);
} catch (noOrganization) {

Просмотреть файл

@ -6,17 +6,11 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { jsonError } from '../../../middleware/jsonError';
import { IProviders, NoCacheNoBackground, ReposAppRequest } from '../../../transitional';
import { Organization } from '../../../business/organization';
import { MemberSearch } from '../../../business/memberSearch';
import { Operations } from '../../../business/operations';
import { corporateLinkToJson } from '../../../business/corporateLink';
import { OrganizationMember } from '../../../business/organizationMember';
import { Team } from '../../../business/team';
import { TeamMember } from '../../../business/teamMember';
import { jsonError } from '../../../middleware';
import { getProviders, NoCacheNoBackground, ReposAppRequest } from '../../../transitional';
import LeakyLocalCache, { getLinksLightCache } from '../leakyLocalCache';
import JsonPager from '../jsonPager';
import { OrganizationMember, TeamMember, Operations, Team, Organization, MemberSearch, corporateLinkToJson } from '../../../business';
const router = express.Router();
@ -59,7 +53,7 @@ type PeopleSearchOptions = {
}
export async function equivalentLegacyPeopleSearch(req: ReposAppRequest, options?: PeopleSearchOptions) {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const links = await getLinksLightCache(operations);
const org = req.organization ? req.organization.name : null;
const orgId = req.organization ? (req.organization as Organization).id : null;

Просмотреть файл

@ -6,9 +6,9 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { jsonError } from '../../../middleware/jsonError';
import { ErrorHelper, IProviders, LocalApiRepoAction, ReposAppRequest } from '../../../transitional';
import { Repository } from '../../../business/repository';
import { jsonError } from '../../../middleware';
import { ErrorHelper, getProviders, LocalApiRepoAction, ReposAppRequest } from '../../../transitional';
import { Repository } from '../../../business';
import { IndividualContext } from '../../../user';
import NewRepositoryLockdownSystem from '../../../features/newRepositoryLockdown';
import { AddRepositoryPermissionsToRequest, getContextualRepositoryPermissions } from '../../../middleware/github/repoPermissions';
@ -68,7 +68,7 @@ router.get('/exists', asyncHandler(async (req: RequestWithRepo, res, next) => {
}));
router.patch('/renameDefaultBranch', asyncHandler(AddRepositoryPermissionsToRequest), asyncHandler(async function (req: RequestWithRepo, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const repoPermissions = getContextualRepositoryPermissions(req);
const targetBranchName = req.body.default_branch;
@ -83,7 +83,7 @@ router.patch('/renameDefaultBranch', asyncHandler(AddRepositoryPermissionsToRequ
router.post('/archive', asyncHandler(AddRepositoryPermissionsToRequest), asyncHandler(async function (req: RequestWithRepo, res, next) {
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { insights } = providers;
const repoPermissions = getContextualRepositoryPermissions(req);
if (!repoPermissions.allowAdministration) {
@ -140,7 +140,7 @@ router.post('/archive', asyncHandler(AddRepositoryPermissionsToRequest), asyncHa
router.delete('/', asyncHandler(AddRepositoryPermissionsToRequest), asyncHandler(async function (req: RequestWithRepo, res, next) {
// NOTE: duplicated code from /routes/org/repos.ts
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { insights } = providers;
const insightsPrefix = 'DeleteRepo';
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
@ -209,7 +209,7 @@ router.delete('/', asyncHandler(AddRepositoryPermissionsToRequest), asyncHandler
}
return next(jsonError(noExistingMetadata, 404));
}
const { operations, repositoryMetadataProvider } = req.app.settings.providers as IProviders;
const { operations, repositoryMetadataProvider } = getProviders(req);
const lockdownSystem = new NewRepositoryLockdownSystem({ operations, organization, repository, repositoryMetadataProvider });
await lockdownSystem.deleteLockedRepository(false /* delete for any reason */, true /* deleted by the original user instead of ops */);
return res.json({

Просмотреть файл

@ -6,9 +6,9 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { jsonError } from '../../../middleware/jsonError';
import { IProviders, ReposAppRequest } from '../../../transitional';
import { Repository } from '../../../business/repository';
import { jsonError } from '../../../middleware';
import { getProviders, IProviders, ReposAppRequest } from '../../../transitional';
import { Repository } from '../../../business';
import RouteRepo from './repo';
import JsonPager from '../jsonPager';
@ -17,7 +17,7 @@ const router = express.Router();
router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { organization } = req;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const pager = new JsonPager<Repository>(req, res);
const searchOptions = {
q: (req.query.q || '') as string,

Просмотреть файл

@ -5,18 +5,16 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { corporateLinkToJson, ICorporateLink } from '../../../business/corporateLink';
import { OrganizationMember } from '../../../business/organizationMember';
import { TeamJsonFormat } from '../../../business/team';
import { TeamRepositoryPermission } from '../../../business/teamRepositoryPermission';
import { getContextualTeam } from '../../../middleware/github/teamPermissions';
import { jsonError } from '../../../middleware/jsonError';
import { jsonError } from '../../../middleware';
import { sortRepositoriesByNameCaseInsensitive } from '../../../routes/org/team';
import { IProviders, NoCacheNoBackground, ReposAppRequest } from '../../../transitional';
import { getProviders, NoCacheNoBackground, ReposAppRequest } from '../../../transitional';
import JsonPager from '../jsonPager';
import { getLinksLightCache } from '../leakyLocalCache';
import { equivalentLegacyPeopleSearch } from './people';
import { TeamJsonFormat, TeamRepositoryPermission, OrganizationMember, corporateLinkToJson, ICorporateLink } from '../../../business';
const router = express.Router();
@ -68,7 +66,7 @@ router.get('/members', asyncHandler(async (req: ReposAppRequest, res, next) => {
}));
router.get('/maintainers', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
try {
const forceRefresh = !!req.query.refresh;
const team = getContextualTeam(req);

Просмотреть файл

@ -6,15 +6,15 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { jsonError } from '../../middleware/jsonError';
import { ErrorHelper, IProviders, ReposAppRequest } from '../../transitional';
import { jsonError } from '../../middleware';
import { ErrorHelper, getProviders, ReposAppRequest } from '../../transitional';
import RouteOrganization from './organization';
const router = express.Router();
router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
try {
const orgs = operations.getOrganizations();
const dd = orgs.map(org => { return org.asClientJson(); });
@ -25,7 +25,7 @@ router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
}));
router.use('/:orgName', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const { orgName } = req.params;
try {
const org = operations.getOrganization(orgName);

Просмотреть файл

@ -4,7 +4,7 @@
//
import { Organization, MemberSearch, ICrossOrganizationMembersResult, Operations } from '../../business';
import { IProviders, ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import LeakyLocalCache, { getLinksLightCache } from './leakyLocalCache';
// BAD PRACTICE: leaky local cache
@ -22,7 +22,7 @@ export async function getPeopleAcrossOrganizations(operations: Operations) {
}
export async function equivalentLegacyPeopleSearch(req: ReposAppRequest) {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const links = await getLinksLightCache(operations);
const org = req.organization ? req.organization.name : null;
const orgId = req.organization ? (req.organization as Organization).id : null;

Просмотреть файл

@ -5,13 +5,13 @@
import asyncHandler from 'express-async-handler';
import { jsonError } from '../../middleware/jsonError';
import { IProviders, ReposAppRequest } from '../../transitional';
import { jsonError } from '../../middleware';
import { getProviders, ReposAppRequest } from '../../transitional';
import { AccountJsonFormat } from '../../business';
export default asyncHandler(async (req: ReposAppRequest, res, next) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { operations, queryCache } = providers;
const login = req.params.login as string;
try {

Просмотреть файл

@ -5,18 +5,17 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { Repository } from '../../business/repository';
import { jsonError } from '../../middleware/jsonError';
import { IProviders, ReposAppRequest } from '../../transitional';
import { Repository } from '../../business';
import { jsonError } from '../../middleware';
import { getProviders, ReposAppRequest } from '../../transitional';
import JsonPager from './jsonPager';
import { RepositorySearchSortOrder, searchRepos } from './organization/repos';
const router = express.Router();
router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const pager = new JsonPager<Repository>(req, res);
const searchOptions = {
q: (req.query.q || '') as string,

Просмотреть файл

@ -5,12 +5,10 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { ICrossOrganizationMembershipByOrganization, Operations } from '../../business/operations';
import { Team, TeamJsonFormat } from '../../business/team';
import { jsonError } from '../../middleware/jsonError';
import { IProviders, ReposAppRequest } from '../../transitional';
import { ICrossOrganizationMembershipByOrganization, Operations, Team, TeamJsonFormat } from '../../business';
import { jsonError } from '../../middleware';
import { getProviders, ReposAppRequest } from '../../transitional';
import JsonPager from './jsonPager';
const router = express.Router();
@ -36,7 +34,7 @@ async function getCrossOrganizationTeams(operations: Operations): Promise<Team[]
}
router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const pager = new JsonPager<Team>(req, res);
const q: string = (req.query.q ? req.query.q as string : null) || '';
try {

Просмотреть файл

@ -9,7 +9,7 @@
import _ from 'lodash';
import { jsonError } from '../middleware';
import { ICustomizedNewRepositoryLogic, INewRepositoryContext, IProviders } from '../transitional';
import { getProviders, ICustomizedNewRepositoryLogic, INewRepositoryContext, IProviders } from '../transitional';
import { ICreateRepositoryResult, Organization } from '../business/organization';
import { RepositoryMetadataEntity, GitHubRepositoryVisibility, GitHubRepositoryPermission, RepositoryLockdownState } from '../entities/repositoryMetadata/repositoryMetadata';
import RenderHtmlMail from '../lib/emailRender';
@ -53,7 +53,7 @@ export async function CreateRepository(req, logic: ICustomizedNewRepositoryLogic
if (!req.organization) {
throw jsonError(new Error('No organization available in the route.'), 400);
}
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
const mailProvider = providers.mailProvider;
const repositoryMetadataProvider = providers.repositoryMetadataProvider;
@ -136,7 +136,7 @@ export async function CreateRepository(req, logic: ICustomizedNewRepositoryLogic
}
let repository: Repository = null;
if (!existingRepoId) {
req.app.settings.providers.insights.trackEvent({
providers.insights?.trackEvent({
name: 'ApiRepoTryCreateForOrg',
properties: {
parameterName: parameters.name,
@ -153,7 +153,7 @@ export async function CreateRepository(req, logic: ICustomizedNewRepositoryLogic
repository = organization.repositoryFromEntity(createResult.repository);
}
} catch (error) {
req.app.settings.providers.insights.trackEvent({
providers.insights?.trackEvent({
name: 'ApiRepoCreateForOrgGitHubFailure',
properties: {
parameterName: parameters.name,
@ -185,7 +185,7 @@ export async function CreateRepository(req, logic: ICustomizedNewRepositoryLogic
throw jsonError(error, error.status || 500);
}
response = createResult.response;
req.app.settings.providers.insights.trackEvent({
providers.insights?.trackEvent({
name: 'ApiRepoCreateForOrg',
properties: {
parameterName: parameters.name,
@ -220,7 +220,7 @@ export async function CreateRepository(req, logic: ICustomizedNewRepositoryLogic
const account = await operations.getAccountByUsername(metadata.createdByThirdPartyUsername);
metadata.createdByThirdPartyId = account.id.toString();
} catch (noAvailableUsername) {
req.app.settings.providers.insights.trackEvent({
providers.insights?.trackEvent({
name: 'ApiRepoCreateInvalidUsername',
properties: {
username: metadata.createdByThirdPartyUsername,
@ -399,7 +399,7 @@ function downgradeBroadAccessTeams(organization, teams) {
}
async function sendEmail(req, logic: ICustomizedNewRepositoryLogic, createContext: INewRepositoryContext, mailProvider: IMailProvider, apiKeyRow, correlationId: string, repoCreateResults, approvalRequest: RepositoryMetadataEntity, msProperties, existingRepoId: any, repository: Repository, createdUserLink: ICorporateLink): Promise<void> {
const { config, operations, viewServices } = req.app.settings.providers as IProviders;
const { config, operations, viewServices } = getProviders(req);
const excludeNotificationsValue = config.notifications?.reposNotificationExcludeForUsers;
let excludeNotifications = [];
if (excludeNotificationsValue) {
@ -481,7 +481,7 @@ async function sendEmail(req, logic: ICustomizedNewRepositoryLogic, createContex
isNotBootstrap: true,
};
try {
mail.content = await RenderHtmlMail(req.app.settings.runtimeConfig.typescript.appDirectory, emailTemplate, contentOptions);
mail.content = await RenderHtmlMail(config.typescript.appDirectory, emailTemplate, contentOptions);
} catch (renderError) {
req.insights.trackException({
exception: renderError,
@ -514,7 +514,7 @@ async function sendEmail(req, logic: ICustomizedNewRepositoryLogic, createContex
additionalMail.to = operationsMails;
contentOptions.reason = `You are receiving this e-mail as the operations contact address(es) ${operationsMails.join(', ')}. A repo has been created or classified.`;
try {
additionalMail.content = await RenderHtmlMail(req.app.settings.runtimeConfig.typescript.appDirectory, emailTemplate, contentOptions);
additionalMail.content = await RenderHtmlMail(config.typescript.appDirectory, emailTemplate, contentOptions);
} catch (renderError) {
console.dir(renderError);
return;

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IProviders } from '../transitional';
import { getProviders, IProviders } from '../transitional';
import { setIdentity } from '../middleware/business/authentication';
import { AddLinkToRequest } from '../middleware/links';
import { jsonError } from '../middleware';
@ -66,7 +66,7 @@ router.use(asyncHandler(AddLinkToRequest));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
router.get('/', (req: IApiRequest, res) => {
const operations = req.app.settings.providers.operations;
const { operations } = getProviders(req);
// Basic info route, used to validate new users
const apiContext = req.apiContext;
@ -122,7 +122,7 @@ router.get('/metadata', asyncHandler(getLocalEncryptionKeyMiddleware), (req: IAp
const apiContext = req.apiContext;
const localKey = res.localKey;
const operations = req.app.settings.providers.operations;
const { operations } = getProviders(req);
const ghi = apiContext.getGitHubIdentity();
const id = ghi ? ghi.id : null;
const login = ghi ? ghi.username : null;
@ -183,7 +183,7 @@ function getSanitizedOrganizations(operations) {
}
async function getLocalEncryptionKeyMiddleware(req: IApiRequest, res, next): Promise<void> {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const localExtensionKeyProvider = providers.localExtensionKeyProvider;
const apiKeyToken = req.apiKeyToken;
const insights = req.insights;

Просмотреть файл

@ -9,7 +9,7 @@ const router = express.Router();
import cors from 'cors';
import { ReposAppRequest, IProviders } from '../transitional';
import { ReposAppRequest, getProviders } from '../transitional';
import { jsonError } from '../middleware';
import { IApiRequest } from '../middleware/apiReposAuth';
@ -91,7 +91,7 @@ router.use('/:org', function (req: IApiRequest, res, next) {
return next(jsonError('The key is not authorized to use the repo create APIs', 401));
}
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
let organization = null;
try {
@ -104,7 +104,7 @@ router.use('/:org', function (req: IApiRequest, res, next) {
});
router.post('/:org/repos', asyncHandler(async function (req: ReposAppRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const convergedObject = Object.assign({}, req.headers);
req.insights.trackEvent({ name: 'ApiRepoCreateRequest', properties: convergedObject });
Object.assign(convergedObject, req.body);

Просмотреть файл

@ -3,7 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import { IProviders } from '../transitional';
import { getProviders } from '../transitional';
export default function JsonErrorHandler(err, req, res, next) {
if (err && err['json']) {
@ -20,7 +20,7 @@ export default function JsonErrorHandler(err, req, res, next) {
res.json({
message: err && err.message ? err.message : 'Error',
});
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
if (providers && providers.insights) {
providers.insights.trackException({ exception: err });
}

Просмотреть файл

@ -3,11 +3,10 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import { IProviders } from '../../transitional';
import { jsonError } from '../../middleware/jsonError';
import { getProviders } from '../../transitional';
import { jsonError } from '../../middleware';
import { IApiRequest } from '../../middleware/apiReposAuth';
import { ICorporateLink } from '../../business/corporateLink';
import { LinkOperationSource } from '../../business/operations';
import { ICorporateLink, LinkOperationSource } from '../../business';
const linkScope = 'link';
@ -16,7 +15,7 @@ const supportedApiVersions = new Set([
]);
export default async function postLinkApi(req: IApiRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { operations } = providers;
const token = req.apiKeyToken;
const apiVersion = (req.query['api-version'] || req.headers['api-version']) as string;

Просмотреть файл

@ -12,7 +12,7 @@ import { ICorporateLink } from '../../business/corporateLink';
import { Operations, ICrossOrganizationMembersResult } from '../../business/operations';
import { IApiRequest } from '../../middleware/apiReposAuth';
import postLinkApi from './link';
import { ErrorHelper } from '../../transitional';
import { ErrorHelper, getProviders } from '../../transitional';
import { wrapError } from '../../utils';
const router = express.Router();
@ -39,7 +39,7 @@ router.use(function (req: IApiRequest, res, next) {
router.post('/', asyncHandler(postLinkApi));
router.get('/', asyncHandler(async (req: IApiRequest, res, next) => {
const operations = req.app.settings.operations;
const { operations } = getProviders(req);
const skipOrganizations = req.query.showOrganizations !== undefined && !!req.query.showOrganizations;
const showTimestamps = req.query.showTimestamps !== undefined && req.query.showTimestamps === 'true';
const results = await getAllUsers(req.apiVersion, operations, skipOrganizations, showTimestamps);
@ -53,7 +53,7 @@ router.get('/:linkid', asyncHandler(async (req: IApiRequest, res, next) => {
return next(jsonError('This API is not supported by the API version you are using.', 400));
}
const linkid = req.params.linkid.toLowerCase();
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const skipOrganizations = req.query.showOrganizations !== undefined && !!req.query.showOrganizations;
const showTimestamps = req.query.showTimestamps !== undefined && req.query.showTimestamps === 'true';
if (operations.providers.queryCache && operations.providers.queryCache.supportsOrganizationMembership) {
@ -93,7 +93,7 @@ router.get('/github/:username', asyncHandler(async (req: IApiRequest, res, next)
return next(jsonError('This API is not supported by the API version you are using.', 400));
}
const username = req.params.username.toLowerCase();
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const skipOrganizations = req.query.showOrganizations !== undefined && !!req.query.showOrganizations;
const showTimestamps = req.query.showTimestamps !== undefined && req.query.showTimestamps === 'true';
if (operations.providers.queryCache && operations.providers.queryCache.supportsOrganizationMembership) {
@ -128,7 +128,7 @@ router.get('/github/:username', asyncHandler(async (req: IApiRequest, res, next)
router.get('/aad/userPrincipalName/:upn', asyncHandler(async (req: IApiRequest, res, next) => {
const upn = req.params.upn;
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const skipOrganizations = req.query.showOrganizations !== undefined && !!req.query.showOrganizations;
const showTimestamps = req.query.showTimestamps !== undefined && req.query.showTimestamps === 'true';
if (operations.providers.queryCache && operations.providers.queryCache.supportsOrganizationMembership) {
@ -184,7 +184,7 @@ router.get('/aad/:id', asyncHandler(async (req: IApiRequest, res, next) => {
const id = req.params.id;
const skipOrganizations = req.query.showOrganizations !== undefined && !!req.query.showOrganizations;
const showTimestamps = req.query.showTimestamps !== undefined && req.query.showTimestamps === 'true';
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
if (operations.providers.queryCache && operations.providers.queryCache.supportsOrganizationMembership) {
// faster implementation
const links = await operations.providers.linkProvider.queryByCorporateId(id);

Просмотреть файл

@ -6,10 +6,10 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { jsonError } from '../../middleware/jsonError';
import { ICorporateLink } from '../../business/corporateLink';
import { Operations, UnlinkPurpose } from '../../business/operations';
import { jsonError } from '../../middleware';
import { ICorporateLink, UnlinkPurpose } from '../../business';
import { IApiRequest } from '../../middleware/apiReposAuth';
import { getProviders } from '../../transitional';
const router = express.Router();
@ -29,9 +29,8 @@ router.use(function (req: ILinksApiRequestWithUnlink, res, next) {
});
router.use('/github/id/:id', asyncHandler(async (req: ILinksApiRequestWithUnlink, res, next) => {
const { operations } = getProviders(req);
const id = req.params.id;
const operations = req.app.settings.operations as Operations;
try {
const link = await operations.linkProvider.getByThirdPartyId(id);
if (!link) {
@ -49,7 +48,7 @@ router.use('*', (req: ILinksApiRequestWithUnlink, res, next) => {
});
router.delete('*', (req: ILinksApiRequestWithUnlink, res, next) => {
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const link = req.unlink;
let purpose: UnlinkPurpose = null;
try {

Просмотреть файл

@ -5,25 +5,27 @@
import express from 'express';
import asyncHandler from 'express-async-handler';
import { jsonError } from '../middleware';
import moment from 'moment';
import { ReposAppRequest } from '../transitional';
const router = express.Router();
import { jsonError } from '../middleware';
import { getProviders, ReposAppRequest } from '../transitional';
import OrganizationWebhookProcessor from '../webhooks/organizationProcessor';
const router = express.Router();
interface IRequestWithRaw extends ReposAppRequest {
_raw?: any;
}
router.use(asyncHandler(async (req: IRequestWithRaw, res, next) => {
const { operations } = getProviders(req);
const body = req.body;
const orgName = body && body.organization && body.organization.login ? body.organization.login : null;
if (!orgName) {
return next(jsonError(new Error('No organization login in the body'), 400));
}
const operations = req.app.settings.providers.operations;
try {
if (!req.organization) {
req.organization = operations.getOrganization(orgName);

Просмотреть файл

@ -9,7 +9,7 @@ import jwksClient from 'jwks-rsa';
import { isJsonError, jsonError } from './jsonError';
import { IApiRequest, wrapErrorForImmediateUserError } from './apiReposAuth';
import { PersonalAccessToken } from '../entities/token/token';
import { IProviders } from '../transitional';
import { getProviders } from '../transitional';
// TODO: Caching of signing keys
@ -58,7 +58,7 @@ function getSigningKeys(header, callback) {
}
async function validateAadAuthorization(req: IApiRequest): Promise<void> {
const { config, insights } = req.app.settings.providers as IProviders;
const { config, insights } = getProviders(req);
const allowedTenants = (config?.microsoft?.api?.aad?.authorizedTenants || '').split(',');
if (!allowedTenants) {

Просмотреть файл

@ -13,7 +13,7 @@ import basicAuth from 'basic-auth';
import crypto from 'crypto';
import { jsonError } from './jsonError';
import { IProviders, ReposAppRequest } from '../transitional';
import { getProviders, IProviders, ReposAppRequest } from '../transitional';
import { PersonalAccessToken } from '../entities/token/token';
export const wrapErrorForImmediateUserError = (err: Error) => {
@ -40,7 +40,7 @@ export default function ReposApiAuthentication(req: IApiRequest, res, next) {
sha1.update(key);
const hashValue = sha1.digest('hex');
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
const apiEventProperties = {
@ -69,14 +69,10 @@ export default function ReposApiAuthentication(req: IApiRequest, res, next) {
if (tokenError && warning) {
apiEventProperties.warning = warning;
}
const insights = req.insights || (req.app.settings.providers as IProviders).insights;
if (insights) {
insights.trackEvent({ name: eventName, properties: apiEventProperties });
}
const insights = getProviders(req).insights;
insights?.trackEvent({ name: eventName, properties: apiEventProperties });
if (tokenError) {
if (insights) {
insights.trackMetric({ name: 'ApiInvalidKey', value: 1 });
}
insights?.trackMetric({ name: 'ApiInvalidKey', value: 1 });
tokenError.skipLog = true;
return next(jsonError(tokenError.statusCode === 404 ? 'Key not authorized' : tokenError.message, 401));
}
@ -84,23 +80,17 @@ export default function ReposApiAuthentication(req: IApiRequest, res, next) {
tokenError = jsonError(warning || 'Key revoked', 403);
wrapErrorForImmediateUserError(tokenError);
tokenError.authErrorMessage = tokenError.message;
if (insights) {
req.insights.trackMetric({ name: 'ApiRevokedKeyAttempt', value: 1 });
}
insights?.trackMetric({ name: 'ApiRevokedKeyAttempt', value: 1 });
return next(tokenError);
}
if (token.isExpired()) {
tokenError = jsonError(warning || 'A revoked key attempted to use an API', 403);
wrapErrorForImmediateUserError(tokenError);
tokenError.authErrorMessage = tokenError.message;
if (insights) {
req.insights.trackMetric({ name: 'ApiExpiredKeyAttempt', value: 1 });
}
insights?.trackMetric({ name: 'ApiExpiredKeyAttempt', value: 1 });
return next(tokenError);
}
if (insights) {
req.insights.trackMetric({ name: 'ApiRequest', value: 1 });
}
insights?.trackMetric({ name: 'ApiRequest', value: 1 });
req.apiKeyToken = token;
req.apiKeyProviderName = 'repos';
return next();

Просмотреть файл

@ -8,13 +8,13 @@ import request = require('requestretry');
import { jsonError } from './jsonError';
import { IApiRequest } from './apiReposAuth';
import { PersonalAccessToken } from '../entities/token/token';
import { IProviders } from '../transitional';
import { getProviders } from '../transitional';
// TODO: consider better caching
const localMemoryCacheVstsToAadId = new Map();
export function AzureDevOpsAuthenticationMiddleware(req: IApiRequest, res, next) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (!config) {
return next(new Error('Missing configuration for the application'));
}
@ -28,7 +28,7 @@ export function AzureDevOpsAuthenticationMiddleware(req: IApiRequest, res, next)
return next(new Error('VSTS collection URL is missing in the environment configuration'));
}
const { graphProvider } = req.app.settings.providers as IProviders;
const { graphProvider } = getProviders(req);
const vstsCollectionUrl = config.authentication.vsts.vstsCollectionUrl;
const connectionDataApi = `${vstsCollectionUrl}/_apis/connectiondata`;

Просмотреть файл

@ -3,9 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import { ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import { wrapError } from '../../utils';
import { Operations } from '../../business/operations';
const cachedLinksRequestKeyName = 'cachedLinks';
@ -13,7 +12,7 @@ export async function ensureAllLinksInMemory(req: ReposAppRequest, res, next) {
if (req[cachedLinksRequestKeyName]) {
return next();
}
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
try {
const links = await operations.getLinks();
req[cachedLinksRequestKeyName] = links;

Просмотреть файл

@ -8,7 +8,7 @@
import _ from 'lodash';
const debug = require('debug')('user');
import { IAppSession, IProviders, ReposAppRequest } from '../../transitional';
import { getProviders, IAppSession, ReposAppRequest } from '../../transitional';
import { ICorporateIdentity, IGitHubIdentity, IndividualContext, GitHubIdentitySource } from '../../user';
import { storeOriginalUrlAsReferrer } from '../../utils';
@ -28,7 +28,7 @@ export async function requireAccessTokenClient(req: ReposAppRequest, res, next)
return next();
}
// This code currently assumes you're using AAD.
const { authorizationCodeClient } = req.app.settings.providers as IProviders;
const { authorizationCodeClient } = getProviders(req);
if (!req.user.azure) {
console.warn('Not an Azure authenticated user');
return signoutThenSignIn(req, res);
@ -58,12 +58,12 @@ function signoutThenSignIn(req, res) {
}
function redirectToSignIn(req, res) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
storeOriginalUrlAsReferrer(req, res, config.authentication.scheme === 'github' ? '/auth/github' : '/auth/azure', 'user is not authenticated and needs to authenticate');
}
export function requireAuthenticatedUserOrSignIn(req: ReposAppRequest, res, next) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (req.isAuthenticated()) {
const expectedAuthenticationProperty = config.authentication.scheme === 'github' ? 'github' : 'azure';
if (req.user && !req.user[expectedAuthenticationProperty]) {
@ -123,7 +123,7 @@ export function setIdentity(req: ReposAppRequest, res, next) {
}
debug(s);
// const insights = req.app.settings.providers.insights;
// const { insights } = getProviders(req);
activeContext.corporateIdentity = corporateIdentity;
activeContext.setSessionBasedGitHubIdentity(gitHubIdentity);

Просмотреть файл

@ -6,9 +6,7 @@
// This route does not use the portal administrator team but instead an explicit
// approved list of corporate usernames.
import express from 'express';
import { ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import { wrapError } from '../../utils';
@ -18,7 +16,7 @@ function denyRoute(next) {
export function AuthorizeOnlyCorporateAdministrators(req: ReposAppRequest, res, next) {
const individualContext = req.individualContext;
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
const administrators: string[] = config && config.administrators && config.administrators.corporateUsernames ? config.administrators.corporateUsernames : null;
const username = individualContext.corporateIdentity.username;
let isAuthorized = false;

Просмотреть файл

@ -3,13 +3,13 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import { IProviders, ReposAppRequest } from '../../transitional';
import { getProviders, ReposAppRequest } from '../../transitional';
import { IndividualContext } from '../../user';
import { jsonError } from '../jsonError';
export default async function getCorporateAliasFromActiveContext(req: ReposAppRequest) {
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const { graphProvider } = req.app.settings.providers as IProviders;
const { graphProvider } = getProviders(req);
if (!activeContext.corporateIdentity || !activeContext.corporateIdentity.id) {
throw jsonError('No corporate identity', 401);
}

Просмотреть файл

@ -4,22 +4,19 @@
//
import { IndividualContext, IIndividualContextOptions, IWebContextOptions, WebContext, SessionUserProperties, WebApiContext } from '../../user';
import { Operations } from '../../business/operations';
import { getProviders } from '../../transitional';
export function webContextMiddleware(req, res, next) {
const operations = req.app.settings.providers.operations as Operations;
const { operations, insights } = getProviders(req);
if (req.apiContext) {
const msg = 'INVALID: API and web contexts should not be mixed';
console.warn(msg);
return next(new Error(msg));
}
if (req.individualContext) {
console.warn('DUPLICATE EFFORT: middleware has already created the individual context');
return next();
}
const webContextOptions: IWebContextOptions = {
baseUrl: '/',
request: req,
@ -29,9 +26,6 @@ export function webContextMiddleware(req, res, next) {
sessionUserProperties: new SessionUserProperties(req.user),
};
const webContext = new WebContext(webContextOptions);
const insights = req.app.settings.providers.insights;
const options : IIndividualContextOptions = {
corporateIdentity: null,
link: null,
@ -42,23 +36,17 @@ export function webContextMiddleware(req, res, next) {
};
const individualContext = new IndividualContext(options);
req.individualContext = individualContext;
return next();
};
export function apiContextMiddleware(req, res, next) {
const operations = req.app.settings.providers.operations as Operations;
const { operations, insights } = getProviders(req);
if (req.individualContext) {
const msg = 'INVALID: API and web contexts should not be mixed';
console.warn(msg);
return next(new Error(msg));
}
const webApiContext = new WebApiContext();
const insights = req.app.settings.providers.insights;
const options : IIndividualContextOptions = {
corporateIdentity: null,
link: null,
@ -69,6 +57,5 @@ export function apiContextMiddleware(req, res, next) {
};
const individualContext = new IndividualContext(options);
req.apiContext = individualContext;
return next();
};

Просмотреть файл

@ -3,6 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import { getProviders } from '../transitional';
interface ICampaignData {
uri?: any;
sub?: any;
@ -55,7 +57,7 @@ export default function initializeCampaigns(app) {
return;
}
const providers = req.app.settings.providers;
const providers = getProviders(req);
const insights = providers.insights;
if (!insights) {
return;
@ -101,7 +103,7 @@ export default function initializeCampaigns(app) {
const uri = `${base}${prefixPortion}${identity}${sub}${queryPortion}`;
res.redirect(uri);
const insights = req.app.settings.providers.insights;
const { insights } = getProviders(req);
if (goGithubQuery) {
data.query = goGithubQuery;
}

Просмотреть файл

@ -1,7 +1,3 @@
import { wrapError } from "../utils";
import { IProviders } from "../transitional";
import { AxiosError } from "axios";
//
// Copyright (c) Microsoft.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
@ -9,7 +5,11 @@ import { AxiosError } from "axios";
/*eslint no-console: ["error", { allow: ["error", "log"] }] */
const querystring = require('querystring');
import querystring from 'querystring';
import { AxiosError } from 'axios';
import { wrapError } from '../utils';
import { getProviders } from '../transitional';
function redactRootPathsFromString(string, path) {
if (typeof string === 'string' && string.includes && string.split) {
@ -51,8 +51,7 @@ const exceptionFieldsOfInterest = [
export default function SiteErrorHandler (err, req, res, next) {
// CONSIDER: Let's eventually decouple all of our error message improvements to another area to keep the error handler intact.
const { applicationProfile } = req.app.settings.providers as IProviders;
var config = null;
const { applicationProfile, config } = getProviders(req);
var correlationId = req.correlationId;
var errorStatus = err ? (err.status || err.statusCode) : undefined;
// Per GitHub: https://developer.github.com/v3/oauth/#bad-verification-code
@ -73,8 +72,7 @@ export default function SiteErrorHandler (err, req, res, next) {
err = wrapError(err, 'The GitHub API is temporarily down. Please try again soon.', false);
}
var primaryUserInstance = req.user ? req.user.github : null;
if (req && req.app && req.app.settings && req.app.settings.runtimeConfig) {
config = req.app.settings.runtimeConfig;
if (config) {
if (config.authentication.scheme !== 'github') {
primaryUserInstance = req.user ? req.user.azure : null;
}

Просмотреть файл

@ -3,7 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import { IProviders, ReposAppRequest } from '../../transitional';
import { getProviders, IProviders, ReposAppRequest } from '../../transitional';
import { Repository } from '../../business/repository';
import { IndividualContext } from '../../user';
import { GitHubCollaboratorPermissionLevel } from '../../business/repositoryPermission';
@ -85,7 +85,7 @@ export async function AddRepositoryPermissionsToRequest(req: ReposAppRequest, re
}
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const repository = req[requestScopedRepositoryKeyName] as Repository;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const permissions = await getComputedRepositoryPermissions(providers, activeContext, repository);
req[repoPermissionsCacheKeyName] = permissions;
return next();

Просмотреть файл

@ -6,9 +6,8 @@
// 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 { ReposAppRequest, IReposError } from "../../transitional";
import { wrapError } from "../../utils";
import { ILinkProvider } from '../../lib/linkProviders';
import { ReposAppRequest, IReposError, getProviders } from '../../transitional';
import { wrapError } from '../../utils';
export function RequireLinkMatchesGitHubSessionExceptPrefixedRoute(prefix: string) {
return requireLinkMatchesGitHubSession.bind(null, prefix);
@ -61,26 +60,6 @@ function requireLinkMatchesGitHubSession(allowedPrefix: string, req: ReposAppReq
}
export async function AddLinkToRequest(req, res, next) {
// TODO: BEFORE MERGE TO PROD:
// Link cleanup logic and routes which may or may not be important
// Important: link cleanup needs, if any
// Not important: multi-user links
// if (error && (error.tooManyLinks === true || error.anotherAccount === true)) {
// // The only URL permitted in this state is the cleanup endpoint and special multiple-account endpoint
// if (req.url === '/link/cleanup' || req.url === '/link/enableMultipleAccounts' || req.url.startsWith('/placeholder')) {
// return next();
// }
// insights.trackEvent({
// name: 'LinkCleanupRedirect',
// properties: {
// message: error.toString(),
// tooManyLinks: error.tooManyLinks === true ? 'too many' : 'no',
// anotherAccount: error.anotherAccount === true ? 'another account' : 'no',
// },
// });
// return res.redirect('/link/cleanup');
// }
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const contextName = req.individualContext ? 'Individual User Context' : 'API Context';
if (!activeContext) {
@ -96,7 +75,7 @@ export async function AddLinkToRequest(req, res, next) {
if (!corporateId) {
return next(new Error('No corporate user information'));
}
const linkProvider = req.app.settings.providers.linkProvider as ILinkProvider;
const { linkProvider } = getProviders(req);
if (!linkProvider) {
return next(new Error('No link provider'));
}

Просмотреть файл

@ -5,18 +5,17 @@
import os from 'os';
// ----------------------------------------------------------------------------
// Set local variables that we want every view to share.
// ----------------------------------------------------------------------------
export default function (req, res, next) {
import { getProviders, ReposAppRequest } from '../transitional';
export default function (req: ReposAppRequest, res, next) {
const { config, viewServices } = getProviders(req);
req.app.locals.correlationId = req.correlationId;
req.app.locals.scrubbedUrl = req.scrubbedUrl;
req.app.locals.serverAddress = req.hostname;
req.app.locals.serverName = os.hostname();
req.app.locals.websiteHostname = process.env.WEBSITE_HOSTNAME;
req.app.locals.appInsightsKey = req.app.settings && req.app.settings.runtimeConfig && req.app.settings.runtimeConfig.telemetry ? req.app.settings.runtimeConfig.telemetry.applicationInsightsKey : null;
req.app.locals.googleAnalyticsKey = req.app.settings && req.app.settings.runtimeConfig && req.app.settings.runtimeConfig.telemetry ? req.app.settings.runtimeConfig.telemetry.googleAnalyticsKey : null;
req.app.locals.viewServices = req.app.settings.viewServices;
req.app.locals.appInsightsKey = config?.telemetry?.applicationInsightsKey;
req.app.locals.googleAnalyticsKey = config?.telemetry?.googleAnalyticsKey;
req.app.locals.viewServices = viewServices;
return next();
};

Просмотреть файл

@ -4,14 +4,15 @@
//
import logger from 'morgan';
import { ReposAppRequest } from '../transitional';
import { getProviders, ReposAppRequest } from '../transitional';
const encryptionMetadataKey = '_ClientEncryptionMetadata2';
const piiFormat = ':id :method :scrubbedUrl :status :response-time ms - :res[content-length] :encryptedSession :correlationId';
const format = ':method :scrubbedUrl :status :response-time ms - :res[content-length] :encryptedSession :correlationId';
logger.token('encryptedSession', function getUserId(req: ReposAppRequest) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (req.session) {
const sessionPassport = (req.session as any).passport;
if (sessionPassport && sessionPassport.user) {
@ -22,7 +23,7 @@ logger.token('encryptedSession', function getUserId(req: ReposAppRequest) {
});
logger.token('id', function getUserId(req: ReposAppRequest) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (config) {
const userType = config.authentication.scheme === 'aad' ? 'azure' : 'github';
return req.user && req.user[userType] && req.user[userType].username ? req.user[userType].username : undefined;

Просмотреть файл

@ -1,9 +1,12 @@
//
// Copyright (c) Microsoft.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// I no longer believe this file FYI... I don't think we need this any longer.
import { getProviders } from '../transitional';
// Office uses a specialized pre-fetch to learn more about hyperlinks before
// opening. As a result, if the Office user agent is in use, and the
// request is not authenticated, we should still just respond with a simple
@ -15,22 +18,20 @@ const GenericOfficeUserAgent = 'ms-office';
const WordUserAgent = 'Microsoft Office Word';
export default function supportOfficeHyperlinks(req, res, next) {
const { insights } = getProviders(req);
const userAgent = req.headers['user-agent'];
const isAuthenticated = req.isAuthenticated ? req.isAuthenticated() : false;
if (userAgent && userAgent.includes && !isAuthenticated && (userAgent.includes(GenericOfficeUserAgent) || userAgent.includes(WordUserAgent))) {
const insights = req.insights || (req.app && req.app.settings && req.app.settings.providers ? req.app.settings.providers.insights : null);
if (insights) {
insights.trackEvent({
name: 'InterceptOfficeHyperlinkRequest',
properties: {
userAgent: userAgent,
isAuthenticated: isAuthenticated,
originalUrl: req.originalUrl,
httpMethod: req.method,
responseType: 200,
},
});
}
insights?.trackEvent({
name: 'InterceptOfficeHyperlinkRequest',
properties: {
userAgent: userAgent,
isAuthenticated: isAuthenticated,
originalUrl: req.originalUrl,
httpMethod: req.method,
responseType: 200,
},
});
return res.send(`When using Microsoft Office, you need to open the hyperlink in your browser to authenticate if needed`);
}
return next();

Просмотреть файл

@ -7,18 +7,20 @@ import querystring from 'querystring';
import { redirectToReferrer, storeReferrer } from '../utils';
import { getGithubAppConfigurationOptions } from './passport/githubStrategy';
import { IProviders, IReposError } from '../transitional';
import { getProviders, IAppSession, IReposError, ReposAppRequest } from '../transitional';
function newSessionAfterAuthentication(req, res, next) {
function newSessionAfterAuthentication(req: ReposAppRequest, res, next) {
// Same site issues
if (req.query && req.query.failure === 'invalid') {
console.log('Invalid callback from AAD. Likely a SameSite issue.');
const { config } = req.app.settings.providers as IProviders;
const { config } = getProviders(req);
if (config?.session?.name) {
try {
const sessionName = config.session.name;
res.clearCookie(sessionName);
req.session.destroy();
return req.session.destroy(() => {
return res.redirect('/');
});
} catch (warnError) {
console.warn(warnError);
}
@ -177,8 +179,8 @@ export default function configurePassport(app, passport, initialConfig) {
});
});
app.get('/auth/github/join', (req, res) => {
var config = req.app.settings.runtimeConfig;
app.get('/auth/github/join', (req: ReposAppRequest, res) => {
const { config } = getProviders(req);
var authorizeRelativeUrl = req.app.settings['runtime/passport/github/authorizeUrl'].replace('https://github.com', '');
var joinUrl = 'https://github.com/join?' + querystring.stringify({
return_to: `${authorizeRelativeUrl}?` + querystring.stringify({
@ -193,17 +195,18 @@ export default function configurePassport(app, passport, initialConfig) {
});
}
function signoutPage(req, res) {
var config = req.app.settings.runtimeConfig;
function signoutPage(req: ReposAppRequest, res) {
const { config } = getProviders(req);
req.logout();
if (req.session) {
delete req.session.enableMultipleAccounts;
delete req.session.selectedGithubId;
const session = req.session as IAppSession
delete session.enableMultipleAccounts;
delete session.selectedGithubId;
}
if (config.authentication.scheme === 'github') {
res.redirect('https://github.com/logout');
} else {
var unlinked = req.query.unlink !== undefined;
const unlinked = req.query.unlink !== undefined;
res.render('message', {
message: unlinked ? `Your ${config.brand.companyName} and GitHub accounts have been unlinked. You no longer have access to any ${config.brand.companyName} organizations, and you have been signed out of this portal.` : 'Goodbye',
title: 'Goodbye',
@ -221,7 +224,7 @@ export default function configurePassport(app, passport, initialConfig) {
// Expanded GitHub auth scope routes
function blockIncreasedScopeForModernApps(req, res, next) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
const { modernAppInUse } = getGithubAppConfigurationOptions(config);
if (modernAppInUse) {
return next(new Error('This site is using the newer GitHub App model and so the increased-scope routes are no longer applicable to it'));
@ -270,8 +273,8 @@ export default function configurePassport(app, passport, initialConfig) {
// links from apps that temporarily prevent sessions. Technically this seems to
// impact Windows users who use Word to open links to the site. Collecting
// telemetry for now.
app.get('/auth/azure/callback', (req, res, next) => {
const insights = req.app.settings.providers.insights;
app.get('/auth/azure/callback', (req: ReposAppRequest, res, next) => {
const { insights } = getProviders(req);
const isAuthenticated = req.isAuthenticated();
if (insights) {
insights.trackEvent({

Просмотреть файл

@ -3,14 +3,14 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
import path from 'path';
import express from 'express';
import fs from 'fs';
import path from 'path';
import appPackage from '../package.json';
import { getStaticBlobCacheFallback } from '../lib/staticBlobCacheFallback';
import { IProviders, ReposAppRequest } from '../transitional';
import express from 'express';
import { getProviders, ReposAppRequest } from '../transitional';
const staticReactPackageNameKey = 'static-react-package-name';
const staticClientPackageName = appPackage[staticReactPackageNameKey];
@ -55,7 +55,7 @@ export async function TryFallbackToBlob(req: ReposAppRequest, res: express.Respo
if (!req.path) {
return false;
}
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const baseUrl = '/react' + req.originalUrl;
if (localFallbackBlobCache.has(baseUrl)) {
providers.insights.trackEvent({name: 'FallbackToBlob', properties: { baseUrl }});

Просмотреть файл

@ -5,6 +5,7 @@
import { jsonError } from './jsonError';
import { IApiRequest } from './apiReposAuth';
import { getProviders } from '../transitional';
// We have made a decision to not use Passport for the API routes, which is why this
// performs some passport-like functionality...
@ -24,9 +25,8 @@ export default function returnCombinedMiddleware(supportedProviders) {
throw new Error('supportedProviders must provide at least one provider to use for auth');
}
return function middleware(req: IApiRequest, res, next) {
const insights = req.app.settings.appInsightsClient;
const { insights } = getProviders(req);
let i = 0;
let currentProvider = supportedProviders[i];
let authErrorMessages = [];
function wrappedNext(error) {
@ -36,42 +36,34 @@ export default function returnCombinedMiddleware(supportedProviders) {
error = jsonError(new Error('No API token was provided by the authentication provider'), 500);
return next(error);
}
// Auth succeeded
return next();
}
if (error.authErrorMessage) {
authErrorMessages.push(error.authErrorMessage);
}
if (error.immediate === true) {
return next(error);
}
++i;
if (i >= totalProviders) {
authErrorMessages.push('Authentication failed, no providers were able to authorize you');
error = jsonError(new Error(authErrorMessages.join('. ')), 401);
error.skipLog = true; // do not log to insights data as an exception
if (insights) {
insights.trackEvent({
name:'MultipleAuthProvidersUnauthorized',
properties: {
message: error.message,
},
});
}
insights?.trackEvent({
name:'MultipleAuthProvidersUnauthorized',
properties: {
message: error.message,
},
});
} else {
// Ignore the error and continue
currentProvider = supportedProviders[i];
return currentProvider(req, res, wrappedNext);
}
if (!error) {
error = jsonError(new Error('Major auth problem'), 500);
}
return next(error);
}
return currentProvider(req, res, wrappedNext);

Просмотреть файл

@ -7,15 +7,15 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IProviders, NoCacheNoBackground, ReposAppRequest } from '../../transitional';
import { getProviders, IProviders, NoCacheNoBackground, ReposAppRequest } from '../../transitional';
import GitHubApplication, { IGitHubAppInstallation } from '../../business/application';
import { OrganizationSetting, IBasicGitHubAppInstallation, SpecialTeam, ISpecialTeam } from '../../entities/organizationSettings/organizationSetting';
import { IndividualContext } from '../../user';
import { Operations } from '../../business/operations';
import { Organization, OrganizationMembershipRole, OrganizationMembershipState } from '../../business/organization';
router.use('/:appId', asyncHandler(async function (req, res, next) {
const providers = req.app.settings.providers as IProviders;
router.use('/:appId', asyncHandler(async function (req: ReposAppRequest, res, next) {
const providers = getProviders(req);
const appId = Number(req.params.appId);
const app = providers.operations.getApplicationById(appId);
if (app) {
@ -64,8 +64,7 @@ function getOrganizationConfiguration(config: any, orgName: string) {
router.use('/:appId/installations/:installationId', asyncHandler(async function (req: ReposAppRequest, res, next) {
const githubApplication = req['githubApplication'] as GitHubApplication;
const installationIdString = req.params.installationId;
const providers = req.app.settings.providers as IProviders;
const config = req.app.settings['runtimeConfig'];
const { config, organizationSettingsProvider } = getProviders(req);
const installationId = Number(installationIdString);
const installation = await githubApplication.getInstallation(installationId);
const invalidReasons = GitHubApplication.isInvalidInstallation(installation);
@ -74,7 +73,6 @@ router.use('/:appId/installations/:installationId', asyncHandler(async function
}
const organizationId = installation.account.id;
const organizationName = installation.account.login;
const organizationSettingsProvider = providers.organizationSettingsProvider;
let settings: OrganizationSetting = null;
try {
settings = await organizationSettingsProvider.getOrganizationSetting(organizationId.toString());
@ -156,7 +154,7 @@ router.post('/:appId/installations/:installationId', asyncHandler(async function
if (!hasImportButtonClicked && !hasElevationButtonClicked && !forceDeleteConfig && !hasCreateButtonClicked && !activate && !deactivate && !removeConfiguration && !addConfiguration && !updateConfig) {
return next(new Error('No supported POST parameters present'));
}
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const githubApplication = req['githubApplication'] as GitHubApplication;
const individualContext = req.individualContext;
const login = individualContext.getGitHubIdentity().username;
@ -310,7 +308,7 @@ router.post('/:appId/installations/:installationId', asyncHandler(async function
router.get('/:appId/installations/:installationId', asyncHandler(async function (req: ReposAppRequest, res, next) {
const githubApplication = req['githubApplication'] as GitHubApplication;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const individualContext = req.individualContext;
const {
staticSettings,

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IProviders, ReposAppRequest, UserAlertType } from '../../transitional';
import { getProviders, ReposAppRequest, UserAlertType } from '../../transitional';
import { sortByCaseInsensitive } from '../../utils';
import GitHubApplication from '../../business/application';
import { OrganizationSetting } from '../../entities/organizationSettings/organizationSetting';
@ -33,7 +33,7 @@ interface IByOrgView {
}
router.post('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { deletesettingsorgname } = req.body;
if (!deletesettingsorgname) {
return next(new Error('Not able to complete this operation'));
@ -58,7 +58,7 @@ router.post('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
}));
router.get('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
const apps = providers.operations.getApplications();
const individualContext = req.individualContext;

Просмотреть файл

@ -8,13 +8,13 @@ import asyncHandler from 'express-async-handler';
import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment';
const router = express.Router();
import { ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, getProviders } from '../../transitional';
import RouteApp from './app';
import RouteApps from './apps';
router.use('*', asyncHandler(async function (req: ReposAppRequest, res, next) {
const { corporateAdministrationProfile } = req.app.settings.providers as IProviders;
const { corporateAdministrationProfile } = getProviders(req);
if (corporateAdministrationProfile && corporateAdministrationProfile.urls) {
req.individualContext.setInitialViewProperty('_corpAdminUrls', corporateAdministrationProfile.urls);
}

Просмотреть файл

@ -4,12 +4,13 @@
//
import express from 'express';
import { IAppSession } from '../transitional';
import { getProviders, IAppSession, ReposAppRequest } from '../transitional';
const router = express.Router();
const redacted = '*****';
interface IRequestWithSession extends express.Request {
app: any;
session: IAppSession;
user: any;
}
@ -23,8 +24,8 @@ interface ISafeUserView {
}
router.get('/', (req: IRequestWithSession, res) => {
const { config } = getProviders(req as any as ReposAppRequest);
const sessionPrefix = req['sessionStore'] && req['sessionStore'].prefix ? req['sessionStore'].prefix + ':' : null;
let config = req.app.settings.runtimeConfig;
const sessionIndex = sessionPrefix ? `${sessionPrefix}${req.session.id}` : req.session.id;
let safeUserView: ISafeUserView = {
cookies: req.cookies,

Просмотреть файл

@ -6,37 +6,39 @@
import express from 'express';
const router = express.Router();
router.get('/', (req, res) => {
const config = req.app.settings.runtimeConfig.obfuscatedConfig;
import { getProviders, ReposAppRequest } from '../transitional';
router.get('/', (req: ReposAppRequest, res) => {
const config = getProviders(req).config;
res.render('explore', {
config: config,
config: config.obfuscatedConfig,
title: 'Explore',
site: 'explore',
});
});
router.get('/registration', (req, res) => {
const config = req.app.settings.runtimeConfig.obfuscatedConfig;
router.get('/registration', (req: ReposAppRequest, res) => {
const config = getProviders(req).config;
res.render('explore', {
config: config,
config: config.obfuscatedConfig,
title: 'Witness',
site: 'registration',
});
});
router.get('/contribute', (req, res) => {
const config = req.app.settings.runtimeConfig.obfuscatedConfig;
router.get('/contribute', (req: ReposAppRequest, res) => {
const config = getProviders(req).config;
res.render('explore', {
config: config,
config: config.obfuscatedConfig,
title: 'Contribute',
site: 'contribute',
});
});
router.get('/data', (req, res) => {
const config = req.app.settings.runtimeConfig.obfuscatedConfig;
router.get('/data', (req: ReposAppRequest, res) => {
const config = getProviders(req).config;
res.render('explore', {
config: config,
config: config.obfuscatedConfig,
title: 'Data',
site: 'data',
});

Просмотреть файл

@ -11,7 +11,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, UserAlertType, hasStaticReactClientApp } from '../transitional';
import { ReposAppRequest, UserAlertType, hasStaticReactClientApp, getProviders } from '../transitional';
import { Organization } from '../business/organization';
@ -60,7 +60,7 @@ dynamicStartupInstance?.routes?.connectAuthenticatedRoutes && dynamicStartupInst
router.use('/settings', SettingsRoute);
router.get('/news', (req: ReposAppRequest, res, next) => {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (config && config.news && config.news.all && config.news.all.length) {
return req.individualContext.webContext.render({
view: 'news',
@ -79,9 +79,9 @@ router.get('/', reactRoute || asyncHandler(async function (req: ReposAppRequest,
const onboarding = req.query.onboarding !== undefined;
const individualContext = req.individualContext;
const link = individualContext.link;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (!link) {
if (!individualContext.getGitHubIdentity()) {
return individualContext.webContext.render({

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, CreateError, hasStaticReactClientApp } from '../transitional';
import { ReposAppRequest, CreateError, hasStaticReactClientApp, getProviders } from '../transitional';
import { IndividualContext } from '../user';
import { storeOriginalUrlAsVariable } from '../utils';
import { AuthorizeOnlyCorporateAdministrators } from '../middleware/business/corporateAdministrators';
@ -20,8 +20,7 @@ import RouteRepos from './repos';
import RouteLegacyOrganizationAdministration from './orgAdmin';
import unlinkRoute from './unlink';
import { Organization } from '../business/organization';
import { Repository } from '../business/repository';
import { Organization, Repository } from '../business';
import orgsRoute from './orgs';
import { injectReactClient } from '../middleware';
@ -63,10 +62,10 @@ router.use('/repos', reactRoute || RouteRepos);
router.use('/undo', RouteUndo);
router.use('/administration', AuthorizeOnlyCorporateAdministrators, RouteAdministration);
router.use('/https?*github.com/:org/:repo', asyncHandler(async (req, res, next) => {
router.use('/https?*github.com/:org/:repo', asyncHandler(async (req: ReposAppRequest, res, next) => {
// Helper method to allow pasting a GitHub URL into the app to go to a repo
const { org, repo } = req.params;
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
if (org && repo) {
let organization: Organization = null;
try {

Просмотреть файл

@ -145,14 +145,14 @@ router.use((req: ReposAppRequest, res, next) => {
// });
// function unlink(req, link, callback) {
// const operations = req.app.settings.providers.operations;
// const { operations, insights, redisClient, config, githubLibrary } = getProviders(req);
// const options = {
// config: req.app.settings.runtimeConfig,
// redisClient: req.app.settings.providers.redisClient,
// githubLibrary: req.app.settings.githubLibrary,
// operations: operations,
// link: link,
// insights: req.insights,
// config,
// redisClient,
// githubLibrary,
// operations,
// link,
// insights,
// };
// new OpenSourceUserContext(options, function (contextError, unlinkContext) {
// if (contextError) {
@ -164,21 +164,4 @@ router.use((req: ReposAppRequest, res, next) => {
// });
// }
// function invalidateCache(req, link, callback) {
// const options = {
// config: req.app.settings.runtimeConfig,
// redisClient: req.app.settings.providers.redisClient,
// githubLibrary: req.app.settings.githubLibrary,
// operations: req.app.settings.providers.operations,
// link: link,
// insights: req.insights,
// };
// new OpenSourceUserContext(options, function (contextError, unlinkContext) {
// if (contextError) {
// return callback(contextError);
// }
// return callback();
// });
// }
export default router;

Просмотреть файл

@ -9,7 +9,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, IAppSession } from '../transitional';
import { ReposAppRequest, IProviders, IAppSession, getProviders } from '../transitional';
import { IndividualContext } from '../user';
import { storeOriginalUrlAsReferrer, wrapError } from '../utils';
import { ICorporateLink } from '../business/corporateLink';
@ -29,7 +29,7 @@ interface IRequestHacked extends ReposAppRequest {
}
router.use((req: IRequestHacked, res, next) => {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (config && config.github && config.github.links && config.github.links.provider && config.github.links.provider.linkingOfflineMessage) {
return next(new Error(`Linking is temporarily offline: ${config.github.links.provider.linkingOfflineMessage}`));
} else {
@ -51,7 +51,7 @@ router.use('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
router.use(asyncHandler(async (req: IRequestHacked, res, next) => {
const individualContext = req.individualContext as IndividualContext;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const insights = providers.insights;
const config = providers.config;
let validateAndBlockGuests = false;
@ -151,7 +151,7 @@ router.get('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
}
}));
async function showLinkPage(req, res) {
async function showLinkPage(req: ReposAppRequest, res) {
const individualContext = req.individualContext as IndividualContext;
function render(options) {
individualContext.webContext.render({
@ -160,13 +160,12 @@ async function showLinkPage(req, res) {
optionalObject: options || {},
})
}
const config = req.app.settings.runtimeConfig;
const graphProvider = req.app.settings.graphProvider;
const { config, graphProvider } = getProviders(req);
if (config.authentication.scheme !== 'aad' || !graphProvider) {
return render(null);
}
const aadId = individualContext.corporateIdentity.id;
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
// By design, we want to log the errors but do not want any individual
// lookup problem to break the underlying experience of letting a user
// link. This is important if someone is new in the company, they may
@ -201,7 +200,7 @@ router.post('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
export async function interactiveLinkUser(isJson: boolean, individualContext: IndividualContext, req, res, next) {
const isServiceAccount = req.body.sa === '1';
const serviceAccountMail = req.body.serviceAccountMail;
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
if (isServiceAccount && !validator.isEmail(serviceAccountMail)) {
const errorMessage = 'Please enter a valid e-mail address for the Service Account maintainer.'
return next(isJson ? jsonError(errorMessage, 400) : wrapError(null, errorMessage, true));
@ -241,7 +240,7 @@ export async function interactiveLinkUser(isJson: boolean, individualContext: In
router.use('/remove', unlinkRoute);
router.get('/reconnect', function (req: ReposAppRequest, res, next) {
const config = req.app.settings.runtimeConfig;
const config = getProviders(req).config;;
if (config.authentication.scheme !== 'aad') {
return next(wrapError(null, 'Account reconnection is only needed for Active Directory authentication applications.', true));
}

Просмотреть файл

@ -7,7 +7,7 @@ import express, { Router } from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, IProviders, getProviders } from '../../transitional';
import { Team } from '../../business/team';
import { IRequestOrganizationPermissions, AddOrganizationPermissionsToRequest } from '../../middleware/github/orgPermissions';
import { OrganizationMembershipState } from '../../business/organization';
@ -42,10 +42,11 @@ router.use(function (req: ReposAppRequest, res, next) {
// Campaign-related redirect to take the user to GitHub
router.get('/', (req: ReposAppRequest, res, next) => {
if (!req.app.settings.providers || !req.app.settings.providers.campaign) {
const providers = getProviders(req);
if (!providers || !providers.campaign) {
return next();
}
return req.app.settings.providers.campaign.redirectGitHubMiddleware(req, res, next, () => {
return providers.campaign.redirectGitHubMiddleware(req, res, next, () => {
return req.organization ? req.organization.name : null;
});
});
@ -84,7 +85,7 @@ router.use(asyncHandler(async (req: ILocalOrgRequest, res, next) => {
// Org membership required endpoints:
router.get('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const approvalProvider = providers.approvalProvider;
const organization = req.organization;
const username = req.individualContext.getGitHubIdentity().username;

Просмотреть файл

@ -11,16 +11,14 @@ const router = express.Router();
import querystring from 'querystring';
import { ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, getProviders } from '../../transitional';
import { Team } from '../../business/team';
import { IndividualContext } from '../../user';
import { storeOriginalUrlAsReferrer, wrapError } from '../../utils';
import { Organization, OrganizationMembershipState, OrganizationMembershipRole } from '../../business/organization';
import { Operations } from '../../business/operations';
import { Organization, OrganizationMembershipState, OrganizationMembershipRole } from '../../business';
import QueryCache from '../../business/queryCache';
import RequireActiveGitHubSession from '../../middleware/github/requireActiveSession';
import { jsonError } from '../../middleware/jsonError';
import { join } from 'lodash';
router.use(function (req: ReposAppRequest, res, next) {
const organization = req.organization;
@ -53,8 +51,8 @@ function queryParamAsBoolean(input: string): boolean {
}
router.get('/', asyncHandler(async function (req: ReposAppRequest, res: express.Response, next: express.NextFunction) {
const operations = req.app.settings.operations as Operations;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { operations } = providers;
const organization = req.organization;
const username = req.individualContext.getGitHubIdentity().username;
const id = req.individualContext.getGitHubIdentity().id;
@ -130,7 +128,7 @@ async function addMemberToOrganizationCache(queryCache: QueryCache, organization
}
router.get('/express', asyncHandler(async function (req: ReposAppRequest, res: express.Response, next: express.NextFunction) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const organization = req.organization;
const onboarding = queryParamAsBoolean(req.query.onboarding as string);
const username = req.individualContext.getGitHubIdentity().username;
@ -202,7 +200,7 @@ router.post('/', joinOrg);
// /orgname/join/byClient
router.post('/byClient', asyncHandler(async (req: ReposAppRequest, res: express.Response, next: express.NextFunction) => {
const { queryCache, insights } = req.app.settings.providers as IProviders;
const { queryCache, insights } = getProviders(req);
const individualContext = req.individualContext as IndividualContext;
const organization = req.organization as Organization;
const onboarding = queryParamAsBoolean(req.query.onboarding as string);

Просмотреть файл

@ -7,10 +7,9 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, UserAlertType } from '../../transitional';
import { ReposAppRequest, UserAlertType, getProviders } from '../../transitional';
import { wrapError } from '../../utils';
import { Organization, OrganizationMembershipState } from '../../business/organization';
import { Operations } from '../../business/operations';
interface IOrganizationMembershipState {
state: OrganizationMembershipState;
@ -26,7 +25,6 @@ interface ILocalLeaveRequest extends ReposAppRequest {
router.use(asyncHandler(async (req: ILocalLeaveRequest, res, next) => {
const organization = req.organization as Organization;
const operations = req.app.settings.operations as Operations;
req.orgLeave = {
state: null,
};
@ -57,7 +55,7 @@ router.get('/', function (req: ILocalLeaveRequest, res) {
router.post('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const organization = req.organization;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
const username = req.individualContext.getGitHubIdentity().username;
const id = req.individualContext.getGitHubIdentity().id;

Просмотреть файл

@ -7,12 +7,12 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, getProviders } from '../../transitional';
import NewRepositoryLockdownSystem from '../../features/newRepositoryLockdown';
import { Organization } from '../../business/organization';
router.get('/', asyncHandler(async function (req: ReposAppRequest, res) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const individualContext = req.individualContext;
const existingRepoId = req.query.existingrepoid as string;
const organization = req.organization as Organization;

Просмотреть файл

@ -7,8 +7,7 @@ import express from 'express';
const router = express.Router();
import asyncHandler from 'express-async-handler';
import { ReposAppRequest } from '../../transitional';
import { Operations } from '../../business/operations';
import { getProviders, ReposAppRequest } from '../../transitional';
interface IUserProfileWarnings {
company?: string;
@ -17,7 +16,7 @@ interface IUserProfileWarnings {
router.get('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const organization = req.organization;
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const config = operations.config;
const onboarding = req.query.onboarding;
const login = req.individualContext.getGitHubIdentity().username;

Просмотреть файл

@ -9,7 +9,7 @@ const router = express.Router();
import _ from 'lodash';
import { ReposAppRequest, IProviders, UserAlertType } from '../../transitional';
import { ReposAppRequest, UserAlertType, getProviders } from '../../transitional';
import { Repository } from '../../business/repository';
import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata';
import { Organization } from '../../business/organization';
@ -42,7 +42,7 @@ router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
}));
router.post('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
const repository = req['repository'] as Repository;
const entity = repository.getEntity();

Просмотреть файл

@ -12,7 +12,7 @@ import lowercaser from '../../middleware/lowercaser';
import { Collaborator, GitHubCollaboratorAffiliationQuery, ICorporateLink, ITemporaryCommandOutput, Organization, OrganizationMember, Repository, TeamPermission } from '../../business';
import { ReposAppRequest, IProviders, UserAlertType, CreateError, NoCacheNoBackground } from '../../transitional';
import { ReposAppRequest, IProviders, UserAlertType, CreateError, NoCacheNoBackground, getProviders } from '../../transitional';
import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata';
import { AddRepositoryPermissionsToRequest, getContextualRepositoryPermissions, IContextualRepositoryPermissions } from '../../middleware/github/repoPermissions';
@ -171,7 +171,7 @@ router.get('/:repoName/delete', asyncHandler(async function (req: ILocalRequest,
router.post('/:repoName/delete', asyncHandler(async function (req: ILocalRequest, res, next) {
// NOTE: this code is also duplicated for now in the client/internal/* folder
// CONSIDER: de-duplicate
const { operations, repositoryMetadataProvider } = req.app.settings.providers as IProviders;
const { operations, repositoryMetadataProvider } = getProviders(req);
const { organization, repository } = req;
const lockdownSystem = new NewRepositoryLockdownSystem({ operations, organization, repository, repositoryMetadataProvider });
await lockdownSystem.deleteLockedRepository(false /* delete for any reason */, true /* deleted by the original user instead of ops */);
@ -187,7 +187,7 @@ export interface IRenameOutput {
router.post('/:repoName/defaultBranch', asyncHandler(AddRepositoryPermissionsToRequest), asyncHandler(async function (req: ILocalRequest, res, next) {
try {
const targetBranchName = req.body.targetBranchName || 'main';
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const activeContext = (req.individualContext || req.apiContext) as IndividualContext;
const repoPermissions = getContextualRepositoryPermissions(req);
const repository = req.repository as Repository;
@ -263,7 +263,7 @@ router.post('/:repoName', asyncHandler(AddRepositoryPermissionsToRequest), async
}));
router.get('/:repoName', asyncHandler(AddRepositoryPermissionsToRequest), asyncHandler(async function (req: ILocalRequest, res, next) {
const { linkProvider, config, graphProvider } = req.app.settings.providers as IProviders;
const { linkProvider, config, graphProvider } = getProviders(req);
const repoPermissions = req.repoPermissions;
const referer = req.headers.referer as string;
const fromReposPage = referer && (referer.endsWith('repos') || referer.endsWith('repos/'));
@ -465,7 +465,7 @@ router.get('/:repoName/permissions', asyncHandler(AddRepositoryPermissionsToRequ
}));
router.get('/:repoName/history', asyncHandler(async function (req: ILocalRequest, res, next) {
const { auditLogRecordProvider } = req.app.settings.providers as IProviders;
const { auditLogRecordProvider } = getProviders(req);
const referer = req.headers.referer as string;
const fromReposPage = referer && (referer.endsWith('repos') || referer.endsWith('repos/'));
const organization = req.organization;

Просмотреть файл

@ -7,9 +7,8 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, UserAlertType } from '../../../../transitional';
import { wrapError } from '../../../../utils';
import { Team } from '../../../../business/team';
import { ReposAppRequest, IProviders, UserAlertType, getProviders } from '../../../../transitional';
import { Team } from '../../../../business';
import { PermissionWorkflowEngine } from '../approvals';
import RenderHtmlMail from '../../../../lib/emailRender';
import { IndividualContext } from '../../../../user';
@ -61,7 +60,7 @@ router.get('/setNote/:action', function (req: ILocalRequest, res) {
});
router.post('/', asyncHandler(async (req: ILocalRequest, res, next) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const { individualContext } = req;
const engine = req.approvalEngine as PermissionWorkflowEngine;
let message = req.body.text as string;

Просмотреть файл

@ -9,7 +9,7 @@ const router = express.Router();
import RouteApproval from './approval';
import { IRequestTeams, ReposAppRequest } from '../../../transitional';
import { getProviders, IRequestTeams, ReposAppRequest } from '../../../transitional';
import { wrapError } from '../../../utils';
import { Team } from '../../../business/team';
import { IApprovalProvider } from '../../../entities/teamJoinApproval/approvalProvider';
@ -111,8 +111,7 @@ interface IRequestPlusApprovalEngine extends IRequestTeams {
router.use('/:requestid', asyncHandler(async function (req: IRequestPlusApprovalEngine, res, next) {
const team = req.team2 as Team;
const requestid = req.params.requestid;
const operations = req.app.settings.providers.operations as Operations;
const approvalProvider = req.app.settings.providers.approvalProvider as IApprovalProvider;
const { approvalProvider, operations } = getProviders(req);
if (!approvalProvider) {
return next(new Error('No approval provider instance available'));
}

Просмотреть файл

@ -9,7 +9,7 @@ const router = express.Router();
import throat from 'throat';
import { ReposAppRequest, IProviders, UserAlertType } from '../../../transitional';
import { ReposAppRequest, IProviders, UserAlertType, getProviders } from '../../../transitional';
import { wrapError } from '../../../utils';
import { ICorporateLink } from '../../../business/corporateLink';
import { Team, GitHubRepositoryType, ITeamMembershipRoleState, GitHubTeamRole } from '../../../business/team';
@ -55,7 +55,7 @@ interface ILocalRequest extends ReposAppRequest {
}
router.use(asyncHandler(async (req: ILocalRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const login = req.individualContext.getGitHubIdentity().username;
const team2 = req.team2 as Team;
try {
@ -72,7 +72,7 @@ router.use(asyncHandler(async (req: ILocalRequest, res, next) => {
}));
router.use(asyncHandler(async (req: ILocalRequest, res, next) => {
const approvalProvider = req.app.settings.providers.approvalProvider as IApprovalProvider;
const { approvalProvider } = getProviders(req);
const team2 = req.team2 as Team;
if (!approvalProvider) {
return next(new Error('No approval provider instance available'));
@ -180,7 +180,7 @@ router.post('/join', asyncHandler(async (req: ILocalRequest, res, next) => {
}
const activeContext = req.individualContext;
const team2 = req.team2 as Team;
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const justification = req.body.justification as string;
const hostname = req.hostname;
const outcome = await submitTeamJoinRequest(providers, activeContext, team2, justification, activeContext.webContext.correlationId, hostname);
@ -447,7 +447,7 @@ enum BasicTeamViewPage {
}
async function basicTeamsView(req: ILocalRequest, display: BasicTeamViewPage) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const showManagementFeatures = parseInt(req.query['inline-management'] as string) == 1;
@ -457,7 +457,7 @@ async function basicTeamsView(req: ILocalRequest, display: BasicTeamViewPage) {
const membershipStatus = req.membershipStatus;
const membershipState = req.membershipState;
const team2 = req.team2 as Team;
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const organization = req.organization as Organization;
const teamMaintainers = req.teamMaintainers as TeamMember[];

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, RequestTeamMemberAddType, UserAlertType, NoCacheNoBackground } from '../../../transitional';
import { ReposAppRequest, RequestTeamMemberAddType, UserAlertType, NoCacheNoBackground, getProviders } from '../../../transitional';
import { Team } from '../../../business/team';
import { TeamMember } from '../../../business/teamMember';
@ -70,7 +70,7 @@ router.use('/add', MiddlewareTeamAdminRequired, (req: ILocalRequest, res, next)
});
router.post('/add', MiddlewareTeamAdminRequired, asyncHandler(async function (req: ILocalRequest, res, next) {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const login = operations.validateGitHubLogin(req.body.username);
const team2 = req.team2 as Team;
await team2.addMaintainer(login);

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, RequestTeamMemberAddType, UserAlertType } from '../../../transitional';
import { ReposAppRequest, RequestTeamMemberAddType, UserAlertType, getProviders } from '../../../transitional';
import { Team } from '../../../business/team';
import { TeamMember } from '../../../business/teamMember';
@ -66,7 +66,7 @@ router.use('/add', MiddlewareTeamAdminRequired, (req: ILocalTeamRequest, res, ne
}, RoutePeopleSearch);
router.post('/remove', MiddlewareTeamAdminRequired, asyncHandler(async (req: ILocalTeamRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const username = operations.validateGitHubLogin(req.body.username);
const team2 = req.team2 as Team;
await team2.removeMembership(username);
@ -76,7 +76,7 @@ router.post('/remove', MiddlewareTeamAdminRequired, asyncHandler(async (req: ILo
}));
router.post('/add', MiddlewareTeamAdminRequired, asyncHandler(async (req: ILocalTeamRequest, res, next) => {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const username = operations.validateGitHubLogin(req.body.username);
const organization = req.organization;
const team2 = req.team2;

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IProviders, ReposAppRequest } from '../transitional';
import { getProviders, IProviders, ReposAppRequest } from '../transitional';
import { requirePortalAdministrationPermission } from '../middleware/business/administration';
import { PostgresLinkProvider } from '../lib/linkProviders/postgres/postgresLinkProvider';
@ -77,19 +77,19 @@ router.get('/', function (req: ReposAppRequest, res) {
})
});
async function queryByGitHubLogin(operations: Operations, graphProvider: any, redisClient: any, login: string): Promise<IUserInformationQuery> {
async function queryByGitHubLogin(providers: IProviders, login: string): Promise<IUserInformationQuery> {
const { operations } = providers;
const query: IUserInformationQuery = {
queryByType: UserQueryByType.ByGitHubUsername,
queryByValue: login,
};
const linkProvider = operations.linkProvider;
let gitHubAccountInfo = null;
try {
gitHubAccountInfo = await operations.getAccountByUsername(login);
} catch (error) {
// They may have renamed their GitHub username, but the ID is the same as it was before...
if (error && error.statusCode === 404) {
const linkByOldName = await getLinkByThirdPartyUsername(operations, graphProvider, redisClient, login) as ICorporateLink;
const linkByOldName = await getLinkByThirdPartyUsername(providers, login) as ICorporateLink;
if (linkByOldName && linkByOldName.thirdPartyId) {
const anotherTryGitHubId = linkByOldName.thirdPartyId;
query.link = linkByOldName;
@ -104,7 +104,7 @@ async function queryByGitHubLogin(operations: Operations, graphProvider: any, re
}
if (!query.link && gitHubAccountInfo && gitHubAccountInfo.login) {
try {
query.link = await getLinkByThirdPartyUsername(operations, graphProvider, redisClient, gitHubAccountInfo.login);
query.link = await getLinkByThirdPartyUsername(providers, gitHubAccountInfo.login);
} catch (queryByLoginAttempt) {
query.noLinkButKnownThirdPartyId = gitHubAccountInfo.id;
if (queryByLoginAttempt.status == 404 /* loose*/) {
@ -114,16 +114,16 @@ async function queryByGitHubLogin(operations: Operations, graphProvider: any, re
}
}
}
return loadInformation(operations, graphProvider, redisClient, query);
return loadInformation(providers, query);
}
function getLinkByThirdPartyUsername(operations: Operations, graphProvider: any, redisClient: any, login: string): Promise<ICorporateLink> {
const linkProvider = operations.linkProvider;
function getLinkByThirdPartyUsername(providers: IProviders, login: string): Promise<ICorporateLink> {
const linkProvider = providers.linkProvider;
return linkProvider.getByThirdPartyUsername(login);
}
async function queryByGitHubId(operations: Operations, graphProvider: any, redisClient: any, thirdPartyId: string): Promise<IUserInformationQuery> {
const linkProvider = operations.linkProvider;
async function queryByGitHubId(providers: IProviders, thirdPartyId: string): Promise<IUserInformationQuery> {
const { linkProvider } = providers;
const link = await linkProvider.getByThirdPartyId(thirdPartyId);
const query: IUserInformationQuery = {
queryByType: UserQueryByType.ByGitHubId,
@ -134,11 +134,11 @@ async function queryByGitHubId(operations: Operations, graphProvider: any, redis
} else {
query.noLinkButKnownThirdPartyId = thirdPartyId;
}
return loadInformation(operations, graphProvider, redisClient, query);
return loadInformation(providers, query);
}
async function queryByCorporateUsername(operations: Operations, graphProvider: any, redisClient: any, upn: string): Promise<IUserInformationQuery> {
const linkProvider = operations.linkProvider;
async function queryByCorporateUsername(providers: IProviders, upn: string): Promise<IUserInformationQuery> {
const linkProvider = providers.linkProvider;
const links = await linkProvider.queryByCorporateUsername(upn);
if (!links || links.length !== 1) {
if (!links || links.length <= 0) {
@ -153,12 +153,12 @@ async function queryByCorporateUsername(operations: Operations, graphProvider: a
queryByValue: upn,
link: links[0],
};
return loadInformation(operations, graphProvider, redisClient, query);
return loadInformation(providers, query);
}
async function loadInformation(operations: Operations, graphProvider: any, redisClient: any, query: IUserInformationQuery): Promise<IUserInformationQuery> {
async function loadInformation(providers: IProviders, query: IUserInformationQuery): Promise<IUserInformationQuery> {
// Input: query type and value; pre-queried and set single link, if present
const { operations } = providers;
const corporateAadId = query.link ? query.link.corporateId : null;
if (corporateAadId) {
try {
@ -251,19 +251,15 @@ async function getGitHubAccountInformationById(operations: Operations, id: strin
router.get('/whois/id/:githubid', function (req: ReposAppRequest, res, next) {
const thirdPartyId = req.params.githubid;
const operations = req.app.settings.providers.operations as Operations;
const graphProvider = req.app.settings.providers.graphProvider;
const redisClient = req.app.settings.providers.redisClient;
queryByGitHubId(operations, graphProvider, redisClient, thirdPartyId).then(query => {
const providers = getProviders(req);
queryByGitHubId(providers, thirdPartyId).then(query => {
req.individualContext.webContext.render({
view: 'organization/whois/result',
title: `Whois by GitHub ID: ${thirdPartyId}`,
state: {
info: query.gitHubUserInfo,
realtimeGraph: query.realtimeGraph,
postUrl: `/organization/whois/id/${thirdPartyId}`,
// new-style
query,
},
@ -283,7 +279,7 @@ interface IIDValue {
router.get('/whois/link/:linkid', asyncHandler(async function (req: ReposAppRequest, res, next) {
const linkId = req.params.linkid;
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const linkProvider = operations.linkProvider as PostgresLinkProvider;
const link = await linkProvider.getByPostgresLinkId(linkId);
return req.individualContext.webContext.render({
@ -317,7 +313,7 @@ router.post('/whois/link/:linkid', asyncHandler(async function (req: ReposAppReq
}
break;
}
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const linkProvider = operations.linkProvider as PostgresLinkProvider;
const link = await linkProvider.getByPostgresLinkId(linkId);
const messages = [
@ -363,7 +359,7 @@ router.post('/whois/link/:linkid', asyncHandler(async function (req: ReposAppReq
}));
router.post('/whois/link/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const { operations } = req.app.settings.providers as IProviders;
const { operations } = getProviders(req);
const allowAdministratorManualLinking = operations?.config?.features?.allowAdministratorManualLinking;
if (!allowAdministratorManualLinking) {
return next(new Error('The manual linking feature is not enabled'));
@ -417,9 +413,7 @@ router.post('/whois/id/:githubid', function (req: ReposAppRequest, res, next) {
const thirdPartyId = req.params.githubid;
const markAsServiceAccount = req.body['mark-as-service-account'];
const unmarkServiceAccount = req.body['unmark-service-account'];
const operations = req.app.settings.operations as Operations;
const graphProvider = req.app.settings.providers.graphProvider;
const redisClient = req.app.settings.providers.redisClient;
const providers = getProviders(req);
let action = OperationsAction.DestroyLink;
if (markAsServiceAccount) {
action = OperationsAction.MarkAsServiceAccount;
@ -430,7 +424,7 @@ router.post('/whois/id/:githubid', function (req: ReposAppRequest, res, next) {
type: IDValueType.ID,
value: thirdPartyId,
};
destructiveLogic(operations, graphProvider, redisClient, idValue, action, req, res, next).then(state => {
destructiveLogic(providers, idValue, action, req, res, next).then(state => {
if (state.independentView) {
return;
}
@ -446,10 +440,8 @@ router.post('/whois/id/:githubid', function (req: ReposAppRequest, res, next) {
router.get('/whois/aad/:upn', function (req: ReposAppRequest, res, next) {
const upn = req.params.upn;
const operations = req.app.settings.providers.operations as Operations;
const graphProvider = req.app.settings.providers.graphProvider;
const redisClient = req.app.settings.providers.redisClient;
queryByCorporateUsername(operations, graphProvider, redisClient, upn).then(query => {
const providers = getProviders(req);
queryByCorporateUsername(providers, upn).then(query => {
req.individualContext.webContext.render({
view: 'organization/whois/result',
title: `Whois by AAD UPN: ${upn}`,
@ -467,17 +459,14 @@ router.get('/whois/aad/:upn', function (req: ReposAppRequest, res, next) {
router.get('/whois/github/:username', function (req: ReposAppRequest, res, next) {
const login = req.params.username;
const operations = req.app.settings.providers.operations;
const graphProvider = req.app.settings.providers.graphProvider;
const redisClient = req.app.settings.providers.redisClient;
queryByGitHubLogin(operations, graphProvider, redisClient, login).then(query => {
const providers = getProviders(req);
queryByGitHubLogin(providers, login).then(query => {
req.individualContext.webContext.render({
view: 'organization/whois/result',
title: `Whois: ${login}`,
state: {
info: query.gitHubUserInfo,
realtimeGraph: query.realtimeGraph,
// new-style
query,
},
@ -489,9 +478,7 @@ router.post('/whois/github/:username', function (req: ReposAppRequest, res, next
const username = req.params.username;
const markAsServiceAccount = req.body['mark-as-service-account'];
const unmarkServiceAccount = req.body['unmark-service-account'];
const operations = req.app.settings.operations as Operations;
const graphProvider = req.app.settings.providers.graphProvider;
const redisClient = req.app.settings.providers.redisClient;
const providers = getProviders(req);
let action = OperationsAction.DestroyLink;
if (markAsServiceAccount) {
action = OperationsAction.MarkAsServiceAccount;
@ -502,7 +489,7 @@ router.post('/whois/github/:username', function (req: ReposAppRequest, res, next
type: IDValueType.Username,
value: username,
};
destructiveLogic(operations, graphProvider, redisClient, identifier, action, req, res, next).then(state => {
destructiveLogic(providers, identifier, action, req, res, next).then(state => {
if (state.independentView) {
return;
}
@ -516,7 +503,8 @@ router.post('/whois/github/:username', function (req: ReposAppRequest, res, next
});
});
async function destructiveLogic(operations: Operations, graphProvider, redisClient, identifier: IIDValue, action: OperationsAction, req, res, next): Promise<any> {
async function destructiveLogic(providers: IProviders, identifier: IIDValue, action: OperationsAction, req, res, next): Promise<any> {
const { operations } = providers;
let usernameInfo = null;
let state = {
results: null,
@ -559,7 +547,7 @@ async function destructiveLogic(operations: Operations, graphProvider, redisClie
let linkQuery = null;
if (thirdPartyId) {
try {
linkQuery = await queryByGitHubId(operations, graphProvider, redisClient, thirdPartyId);
linkQuery = await queryByGitHubId(providers, thirdPartyId);
} catch (oops) {
console.dir(oops);
state.messages.push(`Could not find a corporate link by their GitHub user ID of ${thirdPartyId}`);
@ -567,7 +555,7 @@ async function destructiveLogic(operations: Operations, graphProvider, redisClie
state.messages.push(`Will try next by their GitHub username: ${usernameInfo.login}`);
}
try {
linkQuery = await queryByGitHubLogin(operations, graphProvider, redisClient, thirdPartyUsername);
linkQuery = await queryByGitHubLogin(providers, thirdPartyUsername);
state.messages.push(`Did find a link by their login on GitHub, ${thirdPartyUsername}. Will terminate this ID.`);
} catch (linkByUsernameError) {
state.messages.push(`Could not find a link by login, ${thirdPartyUsername}. Hmm.`);
@ -615,8 +603,8 @@ router.get('/bulkRepoDelete', (req: ReposAppRequest, res) => {
});
});
router.post('/bulkRepoDelete', asyncHandler(async (req, res, next) => {
const operations = req.app.settings.operations as Operations;
router.post('/bulkRepoDelete', asyncHandler(async (req: ReposAppRequest, res, next) => {
const { operations } = getProviders(req);
let repositories = req.body.repositories;
// TODO: FEATURE FLAG: add a feature flag whether this API is available.
if (!repositories) {

Просмотреть файл

@ -10,7 +10,7 @@ const router = express.Router();
import querystring from 'querystring';
import { injectReactClient, TryFallbackToBlob } from '../middleware';
import { hasStaticReactClientApp, IReposRequestWithOrganization } from '../transitional';
import { getProviders, hasStaticReactClientApp, IReposRequestWithOrganization } from '../transitional';
import { wrapError } from '../utils';
import orgRoute from './org/';
@ -29,7 +29,7 @@ async function forwardToOrganizationRoutes (req: IReposRequestWithOrganization,
// This middleware contains both the original GitHub operations types
// as well as the newer implementation. In time this will peel apart.
const orgName = req.params.orgName;
const operations = req.app.settings.operations;
const { operations } = getProviders(req);
try {
const organization = operations.getOrganization(orgName);
req.organization = organization;

Просмотреть файл

@ -6,7 +6,7 @@
import express from 'express';
const router = express.Router();
import { ReposAppRequest } from '../transitional';
import { getProviders, ReposAppRequest } from '../transitional';
import RoutePeopleSearch from './peopleSearch';
import MiddlewareSystemWidePermissions from '../middleware/github/systemWidePermissions';
@ -22,10 +22,11 @@ router.use(function (req: ReposAppRequest, res, next) {
// Campaign-related redirect to take the user to GitHub
router.get('/github/:login', (req: ReposAppRequest, res, next) => {
if (!req.app.settings.providers || !req.app.settings.providers.campaign) {
const providers = getProviders(req);
if (!providers || !providers.campaign) {
return next();
}
return req.app.settings.providers.campaign.redirectGitHubMiddleware(req, res, next, () => {
return providers.campaign.redirectGitHubMiddleware(req, res, next, () => {
const login = req.params.login;
return login ? login : null;
});

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { RequestWithSystemwidePermissions, RequestTeamMemberAddType } from '../transitional';
import { RequestWithSystemwidePermissions, RequestTeamMemberAddType, getProviders } from '../transitional';
import { ensureAllLinksInMemory, getAllLinksFromRequest } from '../middleware/business/allLinks';
@ -65,7 +65,7 @@ async function getPeopleAcrossOrganizations(operations: Operations, options, tea
router.get('/', lowercaser(['sort']), asyncHandler(async (req: IPeopleSearchRequest, res, next) => {
const linksFromMiddleware = getAllLinksFromRequest(req);
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const org = req.organization ? req.organization.name : null;
const orgId = req.organization ? (req.organization as Organization).id : null;
const isPortalSudoer = req.systemWidePermissions && req.systemWidePermissions.allowAdministration === true;

Просмотреть файл

@ -6,21 +6,27 @@
import express from 'express';
const router = express.Router();
import { getProviders, ReposAppRequest } from '../transitional';
// These are Microsoft-specific, we'll remove these eventually.
// TODO: remove from open source version since not helpful having random routes in place
router.use('/data', (req, res) => {
const exploreUrl = req.app.settings.runtimeConfig.urls.explore;
res.redirect(`${exploreUrl}resources/insights`);
router.use('/data', (req: ReposAppRequest, res) => {
const { config } = getProviders(req);
const exploreUrl = config?.urls?.explore;
res.redirect(exploreUrl ? `${exploreUrl}resources/insights` : '/');
});
router.use('/use', (req, res) => {
const exploreUrl = req.app.settings.runtimeConfig.urls.explore;
res.redirect(`${exploreUrl}resources/use`);
router.use('/use', (req: ReposAppRequest, res) => {
const { config } = getProviders(req);
const exploreUrl = config?.urls?.explore;
res.redirect(exploreUrl ? `${exploreUrl}resources/use` : '/');
});
router.use('/release', (req, res) => {
const exploreUrl = req.app.settings.runtimeConfig.urls.explore;
res.redirect(`${exploreUrl}resources/release`);
router.use('/release', (req: ReposAppRequest, res) => {
const { config } = getProviders(req);
const exploreUrl = config?.urls?.explore;
res.redirect(exploreUrl ? `${exploreUrl}resources/release` : '/');
});
export default router;

Просмотреть файл

@ -7,7 +7,7 @@ import asyncHandler from 'express-async-handler';
import express from 'express';
import _ from 'lodash';
import { IReposAppWithTeam, IProviders } from '../transitional';
import { IReposAppWithTeam, getProviders } from '../transitional';
import { Operations } from '../business/operations';
import { Repository } from '../business/repository';
import { Team, GitHubRepositoryType } from '../business/team';
@ -66,7 +66,7 @@ async function getReposAndOptionalTeamPermissions(organizationId: number, operat
}
export default asyncHandler(async function (req: IReposAppWithTeam, res: express.Response, next: express.NextFunction) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const operations = providers.operations;
const queryCache = providers.queryCache;
const individualContext = req.individualContext;

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IReposError, ReposAppRequest, IProviders, UserAlertType } from '../../transitional';
import { IReposError, ReposAppRequest, UserAlertType, getProviders } from '../../transitional';
import { IApprovalProvider } from '../../entities/teamJoinApproval/approvalProvider';
import { TeamJoinApprovalEntity } from '../../entities/teamJoinApproval/teamJoinApproval';
import { safeLocalRedirectUrl } from '../../utils';
@ -65,8 +65,7 @@ export async function Approvals_getUserRequests(operations: Operations, thirdPar
}
router.get('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
const operations = req.app.settings.providers.operations as Operations;
const approvalProvider = req.app.settings.providers.approvalProvider as IApprovalProvider;
const { approvalProvider, operations } = getProviders(req);
if (!approvalProvider) {
return next(new Error('No approval provider instance available'));
}
@ -86,7 +85,7 @@ router.get('/', asyncHandler(async function (req: ReposAppRequest, res, next) {
}));
router.post('/:requestid/cancel', function (req: ReposAppRequest, res, next) {
const approvalProvider = req.app.settings.providers.approvalProvider as IApprovalProvider;
const { approvalProvider } = getProviders(req);
if (!approvalProvider) {
return next(new Error('No approval provider instance available'));
}
@ -115,7 +114,7 @@ router.post('/:requestid/cancel', function (req: ReposAppRequest, res, next) {
router.get('/:requestid', asyncHandler(async function (req: ReposAppRequest, res, next) {
const requestid = req.params.requestid;
const { approvalProvider, operations } = req.app.settings.providers as IProviders;
const { approvalProvider, operations } = getProviders(req);
req.individualContext.webContext.pushBreadcrumb('Your Request');
let isMaintainer = false;
let pendingRequest: TeamJoinApprovalEntity = null;
@ -171,8 +170,8 @@ router.get('/:requestid', asyncHandler(async function (req: ReposAppRequest, res
}));
export function closeOldRequest(isJsonClient: boolean, pendingRequest: TeamJoinApprovalEntity, req: ReposAppRequest, res, next) {
const { approvalProvider } = req.app.settings.providers as IProviders;
const config = req.app.settings.runtimeConfig;
const { approvalProvider } = getProviders(req);
const config = getProviders(req).config;;
const repoApprovalTypesValues = config.github.approvalTypes.repo;
if (repoApprovalTypesValues.length === 0) {
return next(new Error('No repo approval providers configured.'));

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, ICallback } from '../../transitional';
import { ReposAppRequest, getProviders } from '../../transitional';
import { ICorporateLink } from '../../business/corporateLink';
import { Operations } from '../../business/operations';
@ -54,7 +54,7 @@ function createValidator(operations: Operations, link: ICorporateLink, token: st
router.use((req: IRequestWithAuthorizations, res, next) => {
// This is a lightweight, temporary implementation of authorization management to help clear
// stored session tokens for apps like GitHub, VSTS, etc.
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
const link = req.individualContext.link;
const authorizations = [];
if (req.individualContext.webContext.tokens.gitHubReadToken) {

Просмотреть файл

@ -7,10 +7,10 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, CreateError, UserAlertType } from '../../transitional';
import { ReposAppRequest, CreateError, UserAlertType, getProviders } from '../../transitional';
router.use('/:campaignGroupId', (req: ReposAppRequest, res: any, next) => {
const { config } = req.app.settings.providers as IProviders;
const { config } = getProviders(req);
const knownCampaignGroups = (config?.campaigns?.groups || '').toLowerCase().split(',');
req.params.campaignGroupId = req.params.campaignGroupId.toLowerCase();
const { campaignGroupId } = req.params;
@ -29,7 +29,7 @@ router.get('/:campaignGroupId/subscribe', asyncHandler(async (req: ReposAppReque
}));
router.get('/:campaignGroupId', asyncHandler(async (req: ReposAppRequest, res: any, next) => {
const { campaignStateProvider } = req.app.settings.providers as IProviders;
const { campaignStateProvider } = getProviders(req);
if (!campaignStateProvider) {
return next(new Error('This app is not configured for campaign management'));
}
@ -46,7 +46,7 @@ router.get('/:campaignGroupId', asyncHandler(async (req: ReposAppRequest, res: a
}));
async function modifySubscription(isUnsubscribing: boolean, req: ReposAppRequest, res: any, next: any) {
const { campaignStateProvider } = req.app.settings.providers as IProviders;
const { campaignStateProvider } = getProviders(req);
if (!campaignStateProvider) {
return next(new Error('This app is not configured for campaign management'));
}

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders, UserAlertType, ErrorHelper } from '../../transitional';
import { ReposAppRequest, UserAlertType, ErrorHelper, getProviders } from '../../transitional';
import { UserSettings } from '../../entities/userSettings';
export interface IRequestWithUserSettings extends ReposAppRequest {
@ -16,7 +16,7 @@ export interface IRequestWithUserSettings extends ReposAppRequest {
async function getSettings(req: IRequestWithUserSettings, res, next) {
const corporateId = req.individualContext.corporateIdentity.id;
const { userSettingsProvider } = req.app.settings.providers as IProviders;
const { userSettingsProvider } = getProviders(req);
if (!req.userSettings) {
let settings: UserSettings = null;
try {
@ -61,7 +61,7 @@ router.post('/', asyncHandler(async function (req: IRequestWithUserSettings, res
if (!changed) {
return next(new Error('No change to sharing setting.'));
}
const { userSettingsProvider } = req.app.settings.providers as IProviders;
const { userSettingsProvider } = getProviders(req);
await userSettingsProvider.updateUserSettings(req.userSettings);
const message = isOptIn ? 'You have opted in to sharing of contribution data.' : 'You have opted out of sharing contribution data.';
const title = isOptIn ? 'Opt-in saved' : 'Opt-out';

Просмотреть файл

@ -6,7 +6,7 @@
import express from 'express';
const router = express.Router();
import { RequestWithSystemwidePermissions } from '../../transitional';
import { getProviders, RequestWithSystemwidePermissions } from '../../transitional';
import { IndividualContext } from '../../user';
// import { buildConsolidatedMap as buildRecipientMap } from '../../jobs/reports/consolidated';
@ -35,7 +35,7 @@ router.use((req: IRequestWithDigestReports, res, next) => {
// when the Redis server is the same for both reports and the
// app
const providers = req.app.settings.providers;
const providers = getProviders(req);
const config = providers.config;
const reportConfig = config && config.github && config.github.jobs ? config.github.jobs.reports : {};

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, getProviders } from '../../transitional';
import { AddLinkToRequest } from '../../middleware/links/';
import approvalsRoute from './approvals';
@ -21,7 +21,7 @@ import campaignsRoute from './campaigns';
router.use(asyncHandler(AddLinkToRequest));
router.get('/', asyncHandler( async (req: ReposAppRequest, res) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const link = req.individualContext.link;
let legalContactInformation = null;
try {

Просмотреть файл

@ -7,7 +7,7 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IResponseForSettingsPersonalAccessTokens, ReposAppRequest, IProviders } from '../../transitional';
import { ReposAppRequest, getProviders } from '../../transitional';
import { PersonalAccessToken } from '../../entities/token/token';
interface IPersonalAccessTokenForDisplay {
@ -46,7 +46,7 @@ function translateTableToEntities(personalAccessTokens: PersonalAccessToken[]):
}
function getPersonalAccessTokens(req: ReposAppRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
const corporateId = req.individualContext.corporateIdentity.id;
tokenProvider.queryTokensForCorporateId(corporateId).then(tokens => {
@ -75,7 +75,7 @@ router.use(getPersonalAccessTokens);
router.get('/', view);
function createToken(req: ReposAppRequest, res, next) {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
const insights = req.insights;
const description = req.body.description;
@ -126,7 +126,7 @@ router.post('/create', createToken);
router.post('/extension', createToken);
router.post('/delete', asyncHandler(async (req: IRequestForSettingsPersonalAccessTokens, res, next) => {
const providers = req.app.settings.providers as IProviders;
const providers = getProviders(req);
const tokenProvider = providers.tokenProvider;
const revokeAll = req.body.revokeAll === '1';
const revokeIdentifier = req.body.revoke;

Просмотреть файл

@ -7,7 +7,7 @@ import _ from 'lodash';
import asyncHandler from 'express-async-handler';
import express from 'express';
import { ReposAppRequest } from '../transitional';
import { getProviders, ReposAppRequest } from '../transitional';
import { Operations, ICrossOrganizationMembershipByOrganization } from '../business/operations';
import { Team } from '../business/team';
import { UserContext } from '../user/aggregate';
@ -73,7 +73,7 @@ function reduceTeams(collections, property, map) {
}
export default asyncHandler(async function(req: ReposAppRequest, res: express.Response, next: express.NextFunction) {
const operations = req.app.settings.operations as Operations;
const { operations } = getProviders(req);
const isCrossOrg = req.teamsPagerMode === 'orgs';
const aggregations = req.individualContext.aggregations;
const orgName = isCrossOrg ? null : req.organization.name.toLowerCase();

Просмотреть файл

@ -5,6 +5,7 @@
//import * as thisPackage from '../package.json';
import thisPackage = require('../package.json');
import { getProviders, ReposAppRequest } from '../transitional';
// var thisPackage = require('/package.json');
var express = require('express');
@ -32,9 +33,10 @@ function getPackageInfo(config) {
return cachedPackageInformation;
}
router.get('/', function (req, res) {
var config = req.app.settings.runtimeConfig.obfuscatedConfig;
var components = getPackageInfo(config);
router.get('/', function (req: ReposAppRequest, res) {
const { config: completeConfig} = getProviders(req);
const config = completeConfig.obfuscatedConfig;
const components = getPackageInfo(config);
res.render('thanks', {
config: config,
components: components,

Просмотреть файл

@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler';
const router = express.Router();
import { Operations } from '../business/operations';
import { ReposAppRequest, ErrorHelper, UserAlertType } from '../transitional';
import { ReposAppRequest, ErrorHelper, UserAlertType, getProviders } from '../transitional';
import { AuditLogRecord } from '../entities/auditLogRecord/auditLogRecord';
import { daysInMilliseconds } from '../utils';
import { AuditEvents } from '../entities/auditLogRecord';
@ -243,7 +243,7 @@ async function undoTeamAdminRepoPermissionAsync(operations: Operations, entry: I
}
router.use(asyncHandler(async function (req: IHaveUndoCandiates, res, next) {
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
if (!operations.allowUndoSystem) {
res.status(404);
return next(new Error('This feature is unavailable in this application instance'));
@ -269,7 +269,7 @@ router.use(asyncHandler(async function (req: IHaveUndoCandiates, res, next) {
}));
router.post('/', asyncHandler(async (req: IHaveUndoCandiates, res, next) => {
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
const insights = operations.insights;
const link = req.individualContext.link;
const githubId = req.individualContext.getGitHubIdentity().id;
@ -326,7 +326,7 @@ router.post('/', asyncHandler(async (req: IHaveUndoCandiates, res, next) => {
}));
router.get('/', asyncHandler(async (req: IHaveUndoCandiates, res, next) => {
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
const insights = operations.insights;
insights?.trackMetric({ name: 'UndoPageViews', value: 1 });
return req.individualContext.webContext.render({

Просмотреть файл

@ -9,16 +9,16 @@ import express from 'express';
import asyncHandler from 'express-async-handler';
const router = express.Router();
import { IProviders, ReposAppRequest } from '../transitional';
import { getProviders, ReposAppRequest } from '../transitional';
import { wrapError } from '../utils';
import { Operations, UnlinkPurpose } from '../business/operations';
import { UnlinkPurpose } from '../business/operations';
import { OrganizationMembershipState } from '../business/organization';
import { IndividualContext } from '../user';
import { jsonError } from '../middleware';
router.use(asyncHandler(async function (req: ReposAppRequest, res, next) {
const memberOfOrganizations = [];
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
const ghi = req.individualContext.getGitHubIdentity();
if (!ghi || !ghi.username) {
return next(new Error('GitHub identity required'));
@ -46,7 +46,7 @@ router.use(asyncHandler(async function (req: ReposAppRequest, res, next) {
router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
const link = req.individualContext.link;
const id = req.individualContext.getGitHubIdentity().id;
const operations = req.app.settings.providers.operations as Operations;
const { operations } = getProviders(req);
const account = operations.getAccount(id);
const currentOrganizationMemberships = await account.getOperationalOrganizationMemberships();
if (link && id) {
@ -64,7 +64,7 @@ router.get('/', asyncHandler(async (req: ReposAppRequest, res, next) => {
export async function unlinkInteractive(isJson: boolean, individualContext: IndividualContext, req: ReposAppRequest, res, next) {
const id = individualContext.getGitHubIdentity().id;
const { operations, insights } = req.app.settings.providers as IProviders;
const { operations, insights } = getProviders(req);
const terminationOptions = {
reason: 'User used the unlink function on the web site',
purpose: UnlinkPurpose.Self,

Просмотреть файл

@ -299,6 +299,10 @@ export interface ReposAppRequest extends Request {
oauthAccessToken: AccessToken;
}
export function getProviders(req: ReposAppRequest) {
return req.app.settings.providers as IProviders;
}
export interface IReposAppResponse extends Response {
}
@ -556,6 +560,7 @@ interface IAppSessionProperties extends Session {
passport: any;
id: string;
alerts?: IUserAlert[];
referer: string;
}
export interface IAppSession extends IAppSessionProperties {}

Просмотреть файл

@ -7,10 +7,9 @@ import { ReposAppRequest, IReposAppResponse, UserAlertType, IDictionary, IProvid
import { ICorporateLink } from '../business/corporateLink';
import { addBreadcrumb, wrapError } from '../utils';
import { Operations } from "../business/operations";
import { GitHubTeamRole } from "../business/team";
import { UserContext } from "./aggregate";
import { addBreadcrumb } from '../utils';
import { Operations } from '../business/operations';
import { UserContext } from './aggregate';
import pugLoad from 'pug-load';
import fs from 'fs';

Просмотреть файл

@ -9,7 +9,7 @@ import path = require('path');
import { URL } from 'url';
import { IReposError } from './transitional';
import { getProviders, IAppSession, IReposError, ReposAppRequest } from './transitional';
import { DateTime } from 'luxon';
const zlib = require('zlib');
@ -95,20 +95,20 @@ interface IStoreReferrerEventDetails {
redirect?: string;
}
export function storeReferrer(req, res, redirect, optionalReason) {
export function storeReferrer(req: ReposAppRequest, res, redirect, optionalReason) {
const { insights } = getProviders(req);
const eventDetails : IStoreReferrerEventDetails = {
method: 'storeReferrer',
reason: optionalReason || 'unknown reason',
};
if (req.session && req.headers && req.headers.referer && req.session.referer !== undefined && !req.headers.referer.includes('/signout') && !req.session.referer) {
req.session.referer = req.headers.referer;
const session = req.session as IAppSession;
if (session && req.headers && req.headers.referer && session.referer !== undefined && !req.headers.referer.includes('/signout') && !session.referer) {
session.referer = req.headers.referer;
eventDetails.referer = req.headers.referer;
}
if (redirect) {
eventDetails.redirect = redirect;
if (req.insights) {
req.insights.trackEvent({ name: 'RedirectWithReferrer', properties: eventDetails });
}
insights?.trackEvent({ name: 'RedirectWithReferrer', properties: eventDetails });
res.redirect(redirect);
}
};