1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-20 00:08:02 +01:00

Wrong number on the project page regarding members in that project (#1917)

* Fix project member count

* Fix

* Add editors to projects
This commit is contained in:
sjaanus 2022-08-17 12:05:41 +03:00 committed by GitHub
parent 9676165de9
commit 037b8eacd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 25 deletions

View File

@ -29,6 +29,11 @@ export interface IEnvironmentProjectLink {
projectId: string;
}
export interface IProjectMembersCount {
count: number;
project: string;
}
class ProjectStore implements IProjectStore {
private db: Knex;
@ -89,12 +94,11 @@ class ProjectStore implements IProjectStore {
);
projectTimer();
const memberTimer = this.timer('getMemberCount');
const memberCount = await this.db.raw(
`SELECT count(role_id) as member_count, project FROM role_user GROUP BY project`,
);
const memberCount = await this.getMembersCount();
memberTimer();
const memberMap = new Map<string, number>(
memberCount.rows.map((c) => [c.project, Number(c.member_count)]),
memberCount.map((c) => [c.project, Number(c.count)]),
);
return projectsWithFeatureCount.map((r) => {
return { ...r, memberCount: memberMap.get(r.id) };
@ -247,23 +251,75 @@ class ProjectStore implements IProjectStore {
.pluck('project_environments.environment_name');
}
async getMembers(projectId: string): Promise<number> {
const rolesFromProject = this.db('role_permission')
.select('role_id')
.distinct();
const numbers = await this.db('role_user')
.countDistinct('user_id as members')
.where('project', projectId)
.whereIn('role_id', rolesFromProject)
.first();
const { members } = numbers;
if (typeof members === 'string') {
return parseInt(members, 10);
}
async getMembersCount(): Promise<IProjectMembersCount[]> {
const members = await this.db
.select('project')
.from((db) => {
db.select('user_id', 'project')
.from('role_user')
.leftJoin('roles', 'role_user.role_id', 'roles.id')
.where((builder) => builder.whereNot('type', 'root'))
.union((queryBuilder) => {
queryBuilder
.select('user_id', 'project')
.from('group_role')
.leftJoin(
'group_user',
'group_user.group_id',
'group_role.group_id',
);
})
.union((queryBuilder) => {
queryBuilder
.select('user_id', 'projects.name as project')
.from('role_user')
.leftJoin('roles', 'role_user.role_id', 'roles.id')
.crossJoin('projects')
.where((builder) =>
builder
.where('type', 'root')
.where('roles.name', 'Editor'),
);
})
.as('query');
})
.groupBy('project')
.count('user_id');
return members;
}
async getMembersCountByProject(projectId?: string): Promise<number> {
const members = await this.db
.from((db) => {
db.select('user_id')
.from('role_user')
.leftJoin('roles', 'role_user.role_id', 'roles.id')
.where((builder) =>
builder
.where('project', projectId)
.whereNot('type', 'root'),
)
.orWhere((builder) =>
builder.where('type', 'root').where('name', 'Editor'),
)
.union((queryBuilder) => {
queryBuilder
.select('user_id')
.from('group_role')
.leftJoin(
'group_user',
'group_user.group_id',
'group_role.group_id',
)
.where('project', projectId);
})
.as('query');
})
.count()
.first();
return Number(members.count);
}
async count(): Promise<number> {
return this.db
.from(TABLE)

View File

@ -67,7 +67,9 @@ export default class ProjectHealthService {
projectId,
archived,
);
const members = await this.projectStore.getMembers(projectId);
const members = await this.projectStore.getMembersCountByProject(
projectId,
);
return {
name: project.name,
description: project.description,

View File

@ -573,7 +573,7 @@ export default class ProjectService {
}
async getMembers(projectId: string): Promise<number> {
return this.store.getMembers(projectId);
return this.store.getMembersCountByProject(projectId);
}
async getProjectOverview(
@ -588,7 +588,7 @@ export default class ProjectService {
projectId,
archived,
);
const members = await this.store.getMembers(projectId);
const members = await this.store.getMembersCountByProject(projectId);
return {
name: project.name,
environments,

View File

@ -1,4 +1,7 @@
import { IEnvironmentProjectLink } from '../../db/project-store';
import {
IEnvironmentProjectLink,
IProjectMembersCount,
} from '../../db/project-store';
import { IProject, IProjectWithCount } from '../model';
import { Store } from './store';
@ -32,7 +35,8 @@ export interface IProjectStore extends Store<IProject, string> {
addEnvironmentToProject(id: string, environment: string): Promise<void>;
deleteEnvironmentForProject(id: string, environment: string): Promise<void>;
getEnvironmentsForProject(id: string): Promise<string[]>;
getMembers(projectId: string): Promise<number>;
getMembersCountByProject(projectId: string): Promise<number>;
getMembersCount(): Promise<IProjectMembersCount[]>;
getProjectsWithCounts(query?: IProjectQuery): Promise<IProjectWithCount[]>;
count(): Promise<number>;
getAll(query?: IProjectQuery): Promise<IProject[]>;

View File

@ -5,7 +5,10 @@ import {
} from '../../lib/types/stores/project-store';
import { IProject, IProjectWithCount } from '../../lib/types/model';
import NotFoundError from '../../lib/error/notfound-error';
import { IEnvironmentProjectLink } from 'lib/db/project-store';
import {
IEnvironmentProjectLink,
IProjectMembersCount,
} from 'lib/db/project-store';
export default class FakeProjectStore implements IProjectStore {
projects: IProject[] = [];
@ -99,7 +102,7 @@ export default class FakeProjectStore implements IProjectStore {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getMembers(projectId: string): Promise<number> {
async getMembersCountByProject(projectId: string): Promise<number> {
return Promise.resolve(0);
}
@ -120,4 +123,8 @@ export default class FakeProjectStore implements IProjectStore {
this.projects.find((p) => p.id === healthUpdate.id).health =
healthUpdate.health;
}
getMembersCount(): Promise<IProjectMembersCount[]> {
throw new Error('Method not implemented.');
}
}