1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-03-27 00:19:39 +01:00

chore: import IUser instead of User for auth (#5269)

## About the changes
A very subtle change in the way we import IUser makes a huge difference
because previously, instead of importing IUser interface we were
importing User and naming it IUser here:

6f8f21fd48/src/lib/routes/unleash-types.ts (L2)
whereas the correct way of importing the interface is:

eec64b119e/src/lib/routes/unleash-types.ts (L2)
This commit is contained in:
Gastón Fournier 2023-11-06 10:46:59 +01:00 committed by GitHub
parent 5c3fe631f0
commit f16ad4e899
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 88 additions and 88 deletions

View File

@ -1,14 +1,14 @@
import User from '../../types/user';
import { IUser } from '../../types/user';
export interface IChangeRequestAccessReadModel {
canBypassChangeRequest(
project: string,
environment: string,
user?: User,
user?: IUser,
): Promise<boolean>;
canBypassChangeRequestForProject(
project: string,
user?: User,
user?: IUser,
): Promise<boolean>;
isChangeRequestsEnabled(
project: string,

View File

@ -4,7 +4,7 @@ import { IDependentFeaturesStore } from './dependent-features-store-type';
import { FeatureDependency, FeatureDependencyId } from './dependent-features';
import { IDependentFeaturesReadModel } from './dependent-features-read-model-type';
import { EventService } from '../../services';
import { User } from '../../server-impl';
import { IUser } from '../../server-impl';
import { SKIP_CHANGE_REQUEST } from '../../types';
import { IChangeRequestAccessReadModel } from '../change-request-access-service/change-request-access-read-model';
import { extractUsernameFromUser } from '../../util';
@ -72,7 +72,7 @@ export class DependentFeaturesService {
async upsertFeatureDependency(
{ child, projectId }: { child: string; projectId: string },
dependentFeature: CreateDependentFeatureSchema,
user: User,
user: IUser,
): Promise<void> {
await this.stopWhenChangeRequestsEnabled(projectId, user);
@ -158,7 +158,7 @@ export class DependentFeaturesService {
async deleteFeatureDependency(
dependency: FeatureDependencyId,
projectId: string,
user: User,
user: IUser,
): Promise<void> {
await this.stopWhenChangeRequestsEnabled(projectId, user);
@ -187,7 +187,7 @@ export class DependentFeaturesService {
async deleteFeaturesDependencies(
features: string[],
projectId: string,
user: User,
user: IUser,
): Promise<void> {
await this.stopWhenChangeRequestsEnabled(projectId, user);
@ -222,7 +222,7 @@ export class DependentFeaturesService {
return this.dependentFeaturesReadModel.hasAnyDependencies();
}
private async stopWhenChangeRequestsEnabled(project: string, user?: User) {
private async stopWhenChangeRequestsEnabled(project: string, user?: IUser) {
const canBypass =
await this.changeRequestAccessReadModel.canBypassChangeRequestForProject(
project,

View File

@ -27,7 +27,7 @@ import {
ImportTogglesSchema,
ImportTogglesValidateSchema,
} from '../../openapi';
import User from '../../types/user';
import { IUser } from '../../types/user';
import { BadDataError } from '../../error';
import { extractUsernameFromUser } from '../../util';
import {
@ -56,10 +56,10 @@ import { ISegmentService } from '../../segments/segment-service-interface';
export type IImportService = {
validate(
dto: ImportTogglesSchema,
user: User,
user: IUser,
): Promise<ImportTogglesValidateSchema>;
import(dto: ImportTogglesSchema, user: User): Promise<void>;
import(dto: ImportTogglesSchema, user: IUser): Promise<void>;
};
export type IExportService = {
@ -184,7 +184,7 @@ export default class ExportImportService
async validate(
dto: ImportTogglesSchema,
user: User,
user: IUser,
mode = 'regular' as Mode,
): Promise<ImportTogglesValidateSchema> {
const [
@ -249,7 +249,7 @@ export default class ExportImportService
async importVerify(
dto: ImportTogglesSchema,
user: User,
user: IUser,
mode = 'regular' as Mode,
): Promise<void> {
await Promise.all([
@ -264,7 +264,7 @@ export default class ExportImportService
async importFeatureData(
dto: ImportTogglesSchema,
user: User,
user: IUser,
): Promise<void> {
await this.createOrUpdateToggles(dto, user);
await this.importToggleVariants(dto, user);
@ -273,7 +273,7 @@ export default class ExportImportService
await this.importContextFields(dto, user);
}
async import(dto: ImportTogglesSchema, user: User): Promise<void> {
async import(dto: ImportTogglesSchema, user: IUser): Promise<void> {
const cleanedDto = await this.cleanData(dto);
await this.importVerify(cleanedDto, user);
@ -291,7 +291,7 @@ export default class ExportImportService
async importEnvironmentData(
dto: ImportTogglesSchema,
user: User,
user: IUser,
): Promise<void> {
await this.deleteStrategies(dto);
await this.importStrategies(dto, user);
@ -299,7 +299,7 @@ export default class ExportImportService
await this.importDependencies(dto, user);
}
private async importDependencies(dto: ImportTogglesSchema, user: User) {
private async importDependencies(dto: ImportTogglesSchema, user: IUser) {
await Promise.all(
(dto.data.dependencies || []).flatMap((dependency) => {
const projectId = dto.data.features.find(
@ -319,7 +319,7 @@ export default class ExportImportService
);
}
private async importToggleStatuses(dto: ImportTogglesSchema, user: User) {
private async importToggleStatuses(dto: ImportTogglesSchema, user: IUser) {
await Promise.all(
(dto.data.featureEnvironments || []).map((featureEnvironment) =>
this.featureToggleService.updateEnabled(
@ -334,7 +334,7 @@ export default class ExportImportService
);
}
private async importStrategies(dto: ImportTogglesSchema, user: User) {
private async importStrategies(dto: ImportTogglesSchema, user: IUser) {
const hasFeatureName = (
featureStrategy: FeatureStrategySchema,
): featureStrategy is WithRequired<
@ -371,7 +371,7 @@ export default class ExportImportService
);
}
private async importTags(dto: ImportTogglesSchema, user: User) {
private async importTags(dto: ImportTogglesSchema, user: IUser) {
await this.importTogglesStore.deleteTagsForFeatures(
dto.data.features.map((feature) => feature.name),
);
@ -391,7 +391,7 @@ export default class ExportImportService
}
}
private async importContextFields(dto: ImportTogglesSchema, user: User) {
private async importContextFields(dto: ImportTogglesSchema, user: IUser) {
const newContextFields = (await this.getNewContextFields(dto)) || [];
await Promise.all(
newContextFields.map((contextField) =>
@ -408,7 +408,7 @@ export default class ExportImportService
);
}
private async importTagTypes(dto: ImportTogglesSchema, user: User) {
private async importTagTypes(dto: ImportTogglesSchema, user: IUser) {
const newTagTypes = await this.getNewTagTypes(dto);
return Promise.all(
newTagTypes.map((tagType) => {
@ -422,7 +422,7 @@ export default class ExportImportService
);
}
private async importToggleVariants(dto: ImportTogglesSchema, user: User) {
private async importToggleVariants(dto: ImportTogglesSchema, user: IUser) {
const featureEnvsWithVariants =
dto.data.featureEnvironments?.filter(
(featureEnvironment) =>
@ -444,7 +444,7 @@ export default class ExportImportService
);
}
private async createOrUpdateToggles(dto: ImportTogglesSchema, user: User) {
private async createOrUpdateToggles(dto: ImportTogglesSchema, user: IUser) {
const existingFeatures = await this.getExistingProjectFeatures(dto);
const username = extractUsernameFromUser(user);

View File

@ -2,7 +2,7 @@ import { IImportTogglesStore } from './import-toggles-store-type';
import { AccessService, ContextService, TagTypeService } from '../../services';
import { ContextFieldSchema, ImportTogglesSchema } from '../../openapi';
import { ITagType } from '../../types/stores/tag-type-store';
import User from '../../types/user';
import { IUser } from '../../types/user';
import {
CREATE_CONTEXT_FIELD,
CREATE_FEATURE,
@ -67,7 +67,7 @@ export class ImportPermissionsService {
async getMissingPermissions(
dto: ImportTogglesSchema,
user: User,
user: IUser,
mode: Mode,
): Promise<string[]> {
const [
@ -140,7 +140,7 @@ export class ImportPermissionsService {
async verifyPermissions(
dto: ImportTogglesSchema,
user: User,
user: IUser,
mode: Mode,
): Promise<void> {
const missingPermissions = await this.getMissingPermissions(

View File

@ -27,7 +27,6 @@ import {
IFeatureOverview,
IFeatureStrategy,
IFeatureTagStore,
IFeatureToggleClient,
IFeatureToggleClientStore,
IFeatureToggleQuery,
IFeatureToggleStore,
@ -92,7 +91,7 @@ import {
getProjectDefaultStrategy,
} from '../playground/feature-evaluator/helpers';
import { AccessService } from '../../services/access-service';
import { User } from '../../server-impl';
import { IUser } from '../../server-impl';
import { IFeatureProjectUserParams } from './feature-toggle-controller';
import { unique } from '../../util/unique';
import { ISegmentService } from 'lib/segments/segment-service-interface';
@ -464,7 +463,7 @@ class FeatureToggleService {
context: IFeatureStrategyContext,
sortOrders: SetStrategySortOrderSchema,
createdBy: string,
user?: User,
user?: IUser,
): Promise<Saved<any>> {
await this.stopWhenChangeRequestsEnabled(
context.projectId,
@ -548,7 +547,7 @@ class FeatureToggleService {
strategyConfig: Unsaved<IStrategyConfig>,
context: IFeatureStrategyContext,
createdBy: string,
user?: User,
user?: IUser,
): Promise<Saved<IStrategyConfig>> {
await this.stopWhenChangeRequestsEnabled(
context.projectId,
@ -671,7 +670,7 @@ class FeatureToggleService {
updates: Partial<IStrategyConfig>,
context: IFeatureStrategyContext,
userName: string,
user?: User,
user?: IUser,
): Promise<Saved<IStrategyConfig>> {
await this.stopWhenChangeRequestsEnabled(
context.projectId,
@ -835,7 +834,7 @@ class FeatureToggleService {
id: string,
context: IFeatureStrategyContext,
createdBy: string,
user?: User,
user?: IUser,
): Promise<void> {
await this.stopWhenChangeRequestsEnabled(
context.projectId,
@ -1488,7 +1487,7 @@ class FeatureToggleService {
async archiveToggle(
featureName: string,
user: User,
user: IUser,
projectId?: string,
): Promise<void> {
if (projectId) {
@ -1542,7 +1541,7 @@ class FeatureToggleService {
async archiveToggles(
featureNames: string[],
user: User,
user: IUser,
projectId: string,
): Promise<void> {
await this.stopWhenChangeRequestsEnabled(projectId, undefined, user);
@ -1641,7 +1640,7 @@ class FeatureToggleService {
environment: string,
enabled: boolean,
createdBy: string,
user?: User,
user?: IUser,
shouldActivateDisabledStrategies = false,
): Promise<void> {
await Promise.all(
@ -1665,7 +1664,7 @@ class FeatureToggleService {
environment: string,
enabled: boolean,
createdBy: string,
user?: User,
user?: IUser,
shouldActivateDisabledStrategies = false,
): Promise<FeatureToggle> {
await this.stopWhenChangeRequestsEnabled(project, environment, user);
@ -2055,7 +2054,7 @@ class FeatureToggleService {
featureName: string,
project: string,
newVariants: Operation[],
user: User,
user: IUser,
): Promise<FeatureToggle> {
const ft =
await this.featureStrategiesStore.getFeatureToggleWithVariantEnvs(
@ -2082,7 +2081,7 @@ class FeatureToggleService {
project: string,
environment: string,
newVariants: Operation[],
user: User,
user: IUser,
): Promise<IVariant[]> {
const oldVariants = await this.getVariantsForEnv(
featureName,
@ -2136,7 +2135,7 @@ class FeatureToggleService {
featureName: string,
environment: string,
newVariants: IVariant[],
user: User,
user: IUser,
oldVariants?: IVariant[],
): Promise<IVariant[]> {
await variantsArraySchema.validateAsync(newVariants);
@ -2174,7 +2173,7 @@ class FeatureToggleService {
featureName: string,
environment: string,
newVariants: IVariant[],
user: User,
user: IUser,
oldVariants?: IVariant[],
): Promise<IVariant[]> {
await this.stopWhenChangeRequestsEnabled(projectId, environment, user);
@ -2193,7 +2192,7 @@ class FeatureToggleService {
featureName: string,
environments: string[],
newVariants: IVariant[],
user: User,
user: IUser,
): Promise<IVariant[]> {
for (const env of environments) {
await this.stopWhenChangeRequestsEnabled(projectId, env);
@ -2212,7 +2211,7 @@ class FeatureToggleService {
featureName: string,
environments: string[],
newVariants: IVariant[],
user: User,
user: IUser,
): Promise<IVariant[]> {
await variantsArraySchema.validateAsync(newVariants);
const fixedVariants = this.fixVariantWeights(newVariants);
@ -2290,7 +2289,7 @@ class FeatureToggleService {
private async stopWhenChangeRequestsEnabled(
project: string,
environment?: string,
user?: User,
user?: IUser,
) {
const canBypass = environment
? await this.changeRequestAccessReadModel.canBypassChangeRequest(
@ -2311,7 +2310,7 @@ class FeatureToggleService {
project: string,
environment: string,
featureName: string,
user?: User,
user?: IUser,
) {
const hasEnvironment =
await this.featureEnvironmentStore.featureHasEnvironment(

View File

@ -461,9 +461,6 @@ test('If change requests are enabled, cannot change variants without going via C
permissions: [],
seenAt: irrelevantDate,
username: '',
generateImageUrl(): string {
return '';
},
isAPI: true,
},
[],
@ -553,9 +550,6 @@ test('If CRs are protected for any environment in the project stops bulk update
permissions: [],
seenAt: irrelevantDate,
username: '',
generateImageUrl(): string {
return '';
},
isAPI: true,
},
),

View File

@ -16,7 +16,7 @@ import { ApiTokenService } from '../../services/api-token-service';
import { Logger } from '../../logger';
import { AccessService } from '../../services/access-service';
import { IAuthRequest } from '../unleash-types';
import User from '../../types/user';
import { IUser } from '../../types/user';
import { IUnleashConfig } from '../../types/option';
import { ApiTokenType, IApiToken } from '../../types/models/api-token';
import { createApiToken } from '../../schema/api-token-schema';
@ -400,13 +400,13 @@ export class ApiTokenController extends Controller {
private async accessibleTokensByName(
tokenName: string,
user: User,
user: IUser,
): Promise<IApiToken[]> {
const allTokens = await this.accessibleTokens(user);
return allTokens.filter((token) => token.tokenName === tokenName);
}
private async accessibleTokens(user: User): Promise<IApiToken[]> {
private async accessibleTokens(user: IUser): Promise<IApiToken[]> {
const allTokens = await this.apiTokenService.getAllTokens();
if (user.isAPI && user.permissions.includes(ADMIN)) {

View File

@ -9,7 +9,7 @@ import {
resourceCreatedResponseSchema,
} from '../../../openapi';
import { getStandardResponses } from '../../../openapi/util/standard-responses';
import User from '../../../types/user';
import { IUser } from '../../../types/user';
import {
ADMIN,
CREATE_PROJECT_API_TOKEN,
@ -238,7 +238,7 @@ export class ProjectApiTokenController extends Controller {
}
private async accessibleTokens(
user: User,
user: IUser,
project: string,
): Promise<IApiToken[]> {
const allTokens = await this.apiTokenService.getAllTokens();

View File

@ -18,7 +18,7 @@ import { createRequestSchema } from '../../../openapi/util/create-request-schema
import { createResponseSchema } from '../../../openapi/util/create-response-schema';
import { AccessService } from '../../../services';
import { BadDataError, PermissionError } from '../../../../lib/error';
import { User } from 'lib/server-impl';
import { IUser } from 'lib/server-impl';
import { PushVariantsSchema } from 'lib/openapi/spec/push-variants-schema';
import { getStandardResponses } from '../../../openapi';
@ -307,7 +307,7 @@ The backend will also distribute remaining weight up to 1000 after adding the va
}
async checkAccess(
user: User,
user: IUser,
projectId: string,
environments: string[],
permission: string,

View File

@ -4,9 +4,9 @@ import { IUnleashServices } from '../../types';
import { IUnleashConfig } from '../../types/option';
import { Logger } from '../../logger';
import ClientInstanceService from '../../services/client-metrics/instance-service';
import { IAuthRequest, User } from '../../server-impl';
import { IAuthRequest, IUser } from '../../server-impl';
import { IClientApp } from '../../types/model';
import ApiUser from '../../types/api-user';
import ApiUser, { IApiUser } from '../../types/api-user';
import { ALL } from '../../types/models/api-token';
import { NONE } from '../../types/permissions';
import { OpenApiService } from '../../services/openapi-service';
@ -61,7 +61,10 @@ export default class RegisterController extends Controller {
});
}
private static resolveEnvironment(user: User, data: Partial<IClientApp>) {
private static resolveEnvironment(
user: IUser | IApiUser,
data: Partial<IClientApp>,
) {
if (user instanceof ApiUser) {
if (user.environment !== ALL) {
return user.environment;

View File

@ -1,5 +1,5 @@
import { Request } from 'express';
import IUser from '../types/user';
import { IUser } from '../types/user';
import { IApiUser } from '../types';
export interface IAuthRequest<

View File

@ -21,7 +21,7 @@ import {
} from './types';
import User, { IUser } from './types/user';
import ApiUser from './types/api-user';
import ApiUser, { IApiUser } from './types/api-user';
import { Logger, LogLevel } from './logger';
import AuthenticationRequired from './types/authentication-required';
import Controller from './routes/controller';
@ -207,6 +207,7 @@ export type {
IUnleashOptions,
IUnleashConfig,
IUser,
IApiUser,
IUnleashServices,
IAuthRequest,
IApiRequest,

View File

@ -7,15 +7,11 @@ import {
IClientMetricsStoreV2,
} from '../../types/stores/client-metrics-store-v2';
import { clientMetricsSchema } from './schema';
import {
compareAsc,
hoursToMilliseconds,
secondsToMilliseconds,
} from 'date-fns';
import { compareAsc } from 'date-fns';
import { CLIENT_METRICS } from '../../types/events';
import ApiUser, { IApiUser } from '../../types/api-user';
import { ALL } from '../../types/models/api-token';
import User from '../../types/user';
import { IUser } from '../../types/user';
import { collapseHourlyMetrics } from '../../util/collapseHourlyMetrics';
import { LastSeenService } from './last-seen/last-seen-service';
import { generateHourBuckets } from '../../util/time-utils';
@ -222,7 +218,7 @@ export default class ClientMetricsServiceV2 {
}
resolveMetricsEnvironment(
user: User | ApiUser,
user: IUser | IApiUser,
data: { environment?: string },
): string {
if (user instanceof ApiUser) {

View File

@ -9,19 +9,19 @@ import {
PROJECT_FAVORITED,
PROJECT_UNFAVORITED,
} from '../types';
import User from '../types/user';
import { IUser } from '../types/user';
import { extractUsernameFromUser } from '../util';
import { IFavoriteProjectKey } from '../types/stores/favorite-projects';
import EventService from './event-service';
export interface IFavoriteFeatureProps {
feature: string;
user: User;
user: IUser;
}
export interface IFavoriteProjectProps {
project: string;
user: User;
user: IUser;
}
export class FavoritesService {

View File

@ -4,7 +4,7 @@ import { IPatStore } from '../types/stores/pat-store';
import { PAT_CREATED, PAT_DELETED } from '../types/events';
import { IPat } from '../types/models/pat';
import crypto from 'crypto';
import User from '../types/user';
import { IUser } from '../types/user';
import BadDataError from '../error/bad-data-error';
import NameExistsError from '../error/name-exists-error';
import { OperationDeniedError } from '../error/operation-denied-error';
@ -31,7 +31,11 @@ export default class PatService {
this.eventService = eventService;
}
async createPat(pat: IPat, forUserId: number, editor: User): Promise<IPat> {
async createPat(
pat: IPat,
forUserId: number,
editor: IUser,
): Promise<IPat> {
await this.validatePat(pat, forUserId);
pat.secret = this.generateSecretKey();
pat.userId = forUserId;
@ -54,7 +58,7 @@ export default class PatService {
async deletePat(
id: number,
forUserId: number,
editor: User,
editor: IUser,
): Promise<void> {
const pat = await this.patStore.get(id);

View File

@ -1,7 +1,7 @@
import { Logger } from '../logger';
import { IUnleashStores } from '../types/stores';
import { IUnleashConfig } from '../types/option';
import User from '../types/user';
import { IUser } from '../types/user';
import {
IUserFeedback,
IUserFeedbackStore,
@ -20,7 +20,7 @@ export default class UserFeedbackService {
this.logger = getLogger('services/user-feedback-service.js');
}
async getAllUserFeedback(user: User): Promise<IUserFeedback[]> {
async getAllUserFeedback(user: IUser): Promise<IUserFeedback[]> {
if (user.isAPI) {
return [];
}

View File

@ -207,7 +207,7 @@ class UserService {
async createUser(
{ username, email, name, password, rootRole }: ICreateUser,
updatedBy?: User,
updatedBy?: IUser,
): Promise<IUser> {
if (!username && !email) {
throw new BadDataError('You must specify username or email');
@ -244,7 +244,7 @@ class UserService {
return user;
}
private getCreatedBy(updatedBy: User = systemUser) {
private getCreatedBy(updatedBy: IUser = systemUser) {
return updatedBy.username || updatedBy.email;
}
@ -262,7 +262,7 @@ class UserService {
async updateUser(
{ id, name, email, rootRole }: IUpdateUser,
updatedBy?: User,
updatedBy?: IUser,
): Promise<IUser> {
const preUser = await this.store.get(id);
@ -294,7 +294,7 @@ class UserService {
return user;
}
async deleteUser(userId: number, updatedBy?: User): Promise<void> {
async deleteUser(userId: number, updatedBy?: IUser): Promise<void> {
const user = await this.store.get(userId);
await this.accessService.wipeUserPermissions(userId);
await this.sessionService.deleteSessionsForUser(userId);
@ -451,7 +451,7 @@ class UserService {
async createResetPasswordEmail(
receiverEmail: string,
user: User = systemUser,
user: IUser = systemUser,
): Promise<URL> {
const receiver = await this.getByEmail(receiverEmail);
if (!receiver) {

View File

@ -1,7 +1,7 @@
import { Logger } from '../logger';
import { IUnleashStores } from '../types/stores';
import { IUnleashConfig } from '../types/option';
import User from '../types/user';
import { IUser } from '../types/user';
import {
IUserSplash,
IUserSplashStore,
@ -20,7 +20,7 @@ export default class UserSplashService {
this.logger = getLogger('services/user-splash-service.js');
}
async getAllUserSplashes(user: User): Promise<Record<string, boolean>> {
async getAllUserSplashes(user: IUser): Promise<Record<string, boolean>> {
if (user.isAPI) {
return {};
}

View File

@ -18,9 +18,9 @@ export interface UserData {
export interface IUser {
id: number;
name?: string;
username?: string;
email?: string;
name: string;
username: string;
email: string;
inviteLink?: string;
seenAt?: Date;
createdAt?: Date;

View File

@ -137,6 +137,9 @@ class UserStoreMock implements IUserStore {
permissions: [],
loginAttempts: 0,
imageUrl: '',
name: user.name ?? '',
username: user.username ?? '',
email: user.email ?? '',
...user,
});
return Promise.resolve(undefined);