mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
feat: user profile returns user subscriptions (#8656)
This commit is contained in:
parent
2017ab7719
commit
a2a94dd011
@ -190,10 +190,7 @@ export const createStores = (
|
||||
config.flagResolver,
|
||||
),
|
||||
userUnsubscribeStore: new UserUnsubscribeStore(db),
|
||||
userSubscriptionsReadModel: new UserSubscriptionsReadModel(
|
||||
db,
|
||||
eventBus,
|
||||
),
|
||||
userSubscriptionsReadModel: new UserSubscriptionsReadModel(db),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -6,15 +6,18 @@ import {
|
||||
createFakeEventsService,
|
||||
} from '../events/createEventsService';
|
||||
import { FakeUserUnsubscribeStore } from './fake-user-unsubscribe-store';
|
||||
import { UserSubscriptionsReadModel } from './user-subscriptions-read-model';
|
||||
import { FakeUserSubscriptionsReadModel } from './fake-user-subscriptions-read-model';
|
||||
|
||||
export const createUserSubscriptionsService =
|
||||
(config: IUnleashConfig) =>
|
||||
(db: Db): UserSubscriptionsService => {
|
||||
const userUnsubscribeStore = new UserUnsubscribeStore(db);
|
||||
const userSubscriptionsReadModel = new UserSubscriptionsReadModel(db);
|
||||
const eventService = createEventsService(db, config);
|
||||
|
||||
const userSubscriptionsService = new UserSubscriptionsService(
|
||||
{ userUnsubscribeStore },
|
||||
{ userUnsubscribeStore, userSubscriptionsReadModel },
|
||||
config,
|
||||
eventService,
|
||||
);
|
||||
@ -26,10 +29,11 @@ export const createFakeUserSubscriptionsService = (
|
||||
config: IUnleashConfig,
|
||||
): UserSubscriptionsService => {
|
||||
const userUnsubscribeStore = new FakeUserUnsubscribeStore();
|
||||
const userSubscriptionsReadModel = new FakeUserSubscriptionsReadModel();
|
||||
const eventService = createFakeEventsService(config);
|
||||
|
||||
const userSubscriptionsService = new UserSubscriptionsService(
|
||||
{ userUnsubscribeStore },
|
||||
{ userUnsubscribeStore, userSubscriptionsReadModel },
|
||||
config,
|
||||
eventService,
|
||||
);
|
||||
|
@ -2,7 +2,6 @@ import dbInit, { type ITestDb } from '../../../test/e2e/helpers/database-init';
|
||||
import getLogger from '../../../test/fixtures/no-logger';
|
||||
import { UserSubscriptionsReadModel } from './user-subscriptions-read-model';
|
||||
import type { IUserSubscriptionsReadModel } from './user-subscriptions-read-model-type';
|
||||
import EventEmitter from 'events';
|
||||
import { SUBSCRIPTION_TYPES } from './user-subscriptions-read-model-type';
|
||||
import type { IUnleashStores, IUserStore } from '../../types';
|
||||
import type { IUserUnsubscribeStore } from './user-unsubscribe-store-type';
|
||||
@ -21,11 +20,7 @@ beforeAll(async () => {
|
||||
stores = db.stores;
|
||||
userStore = stores.userStore;
|
||||
userUnsubscribeStore = stores.userUnsubscribeStore;
|
||||
const eventBus = new EventEmitter();
|
||||
userSubscriptionsReadModel = new UserSubscriptionsReadModel(
|
||||
db.rawDatabase,
|
||||
eventBus,
|
||||
);
|
||||
userSubscriptionsReadModel = new UserSubscriptionsReadModel(db.rawDatabase);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { Db } from '../../db/db';
|
||||
import type EventEmitter from 'events';
|
||||
import {
|
||||
SUBSCRIPTION_TYPES,
|
||||
type IUserSubscriptionsReadModel,
|
||||
@ -26,7 +25,7 @@ const mapRowToSubscriber = (row) =>
|
||||
export class UserSubscriptionsReadModel implements IUserSubscriptionsReadModel {
|
||||
private db: Db;
|
||||
|
||||
constructor(db: Db, eventBus: EventEmitter) {
|
||||
constructor(db: Db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
|
@ -6,24 +6,38 @@ import type {
|
||||
UnsubscribeEntry,
|
||||
} from './user-unsubscribe-store-type';
|
||||
import type EventService from '../events/event-service';
|
||||
import type { IUserSubscriptionsReadModel } from './user-subscriptions-read-model-type';
|
||||
|
||||
export class UserSubscriptionsService {
|
||||
private userUnsubscribeStore: IUserUnsubscribeStore;
|
||||
|
||||
private userSubscriptionsReadModel: IUserSubscriptionsReadModel;
|
||||
|
||||
private eventService: EventService;
|
||||
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
{ userUnsubscribeStore }: Pick<IUnleashStores, 'userUnsubscribeStore'>,
|
||||
{
|
||||
userUnsubscribeStore,
|
||||
userSubscriptionsReadModel,
|
||||
}: Pick<
|
||||
IUnleashStores,
|
||||
'userUnsubscribeStore' | 'userSubscriptionsReadModel'
|
||||
>,
|
||||
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
|
||||
eventService: EventService,
|
||||
) {
|
||||
this.userUnsubscribeStore = userUnsubscribeStore;
|
||||
this.userSubscriptionsReadModel = userSubscriptionsReadModel;
|
||||
this.eventService = eventService;
|
||||
this.logger = getLogger('services/user-subscription-service.ts');
|
||||
}
|
||||
|
||||
async getUserSubscriptions(userId: number) {
|
||||
return this.userSubscriptionsReadModel.getUserSubscriptions(userId);
|
||||
}
|
||||
|
||||
async subscribe(
|
||||
userId: number,
|
||||
subscription: string,
|
||||
|
@ -9,6 +9,7 @@ test('profileSchema', () => {
|
||||
name: 'Admin',
|
||||
},
|
||||
projects: ['default', 'secretproject'],
|
||||
subscriptions: ['productivity-report'],
|
||||
features: [
|
||||
{ name: 'firstFeature', project: 'default' },
|
||||
{ name: 'secondFeature', project: 'secretproject' },
|
||||
|
@ -7,7 +7,7 @@ export const profileSchema = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
description: 'User profile overview',
|
||||
required: ['rootRole', 'projects', 'features'],
|
||||
required: ['rootRole', 'projects', 'features', 'subscriptions'],
|
||||
properties: {
|
||||
rootRole: {
|
||||
$ref: '#/components/schemas/roleSchema',
|
||||
@ -20,6 +20,14 @@ export const profileSchema = {
|
||||
},
|
||||
example: ['my-projectA', 'my-projectB'],
|
||||
},
|
||||
subscriptions: {
|
||||
description: 'Which email subscriptions this user is subscribed to',
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
example: ['productivity-report'],
|
||||
},
|
||||
features: {
|
||||
description: 'Deprecated, always returns empty array',
|
||||
type: 'array',
|
||||
|
@ -53,6 +53,24 @@ test('should return current user', async () => {
|
||||
});
|
||||
const owaspPassword = 't7GTx&$Y9pcsnxRv6';
|
||||
|
||||
test('should return current profile', async () => {
|
||||
expect.assertions(1);
|
||||
const { request, base } = await getSetup();
|
||||
|
||||
return request
|
||||
.get(`${base}/api/admin/user/profile`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect((res) => {
|
||||
expect(res.body).toMatchObject({
|
||||
projects: [],
|
||||
rootRole: { id: -1, name: 'Viewer', type: 'root' },
|
||||
subscriptions: ['productivity-report'],
|
||||
features: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('should allow user to change password', async () => {
|
||||
const { request, base, userStore } = await getSetup();
|
||||
await request
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
type RolesSchema,
|
||||
} from '../../../openapi/spec/roles-schema';
|
||||
import type { IFlagResolver } from '../../../types';
|
||||
import type { UserSubscriptionsService } from '../../../features/user-subscriptions/user-subscriptions-service';
|
||||
|
||||
class UserController extends Controller {
|
||||
private accessService: AccessService;
|
||||
@ -48,6 +49,8 @@ class UserController extends Controller {
|
||||
|
||||
private flagResolver: IFlagResolver;
|
||||
|
||||
private userSubscriptionsService: UserSubscriptionsService;
|
||||
|
||||
constructor(
|
||||
config: IUnleashConfig,
|
||||
{
|
||||
@ -57,6 +60,7 @@ class UserController extends Controller {
|
||||
userSplashService,
|
||||
openApiService,
|
||||
projectService,
|
||||
transactionalUserSubscriptionsService,
|
||||
}: Pick<
|
||||
IUnleashServices,
|
||||
| 'accessService'
|
||||
@ -65,6 +69,7 @@ class UserController extends Controller {
|
||||
| 'userSplashService'
|
||||
| 'openApiService'
|
||||
| 'projectService'
|
||||
| 'transactionalUserSubscriptionsService'
|
||||
>,
|
||||
) {
|
||||
super(config);
|
||||
@ -74,6 +79,7 @@ class UserController extends Controller {
|
||||
this.userSplashService = userSplashService;
|
||||
this.openApiService = openApiService;
|
||||
this.projectService = projectService;
|
||||
this.userSubscriptionsService = transactionalUserSubscriptionsService;
|
||||
this.flagResolver = config.flagResolver;
|
||||
|
||||
this.route({
|
||||
@ -237,12 +243,16 @@ class UserController extends Controller {
|
||||
): Promise<void> {
|
||||
const { user } = req;
|
||||
|
||||
const projects = await this.projectService.getProjectsByUser(user.id);
|
||||
const [projects, rootRole, subscriptions] = await Promise.all([
|
||||
this.projectService.getProjectsByUser(user.id),
|
||||
this.accessService.getRootRoleForUser(user.id),
|
||||
this.userSubscriptionsService.getUserSubscriptions(user.id),
|
||||
]);
|
||||
|
||||
const rootRole = await this.accessService.getRootRoleForUser(user.id);
|
||||
const responseData: ProfileSchema = {
|
||||
projects,
|
||||
rootRole,
|
||||
subscriptions,
|
||||
features: [],
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user