Skip to content
This repository was archived by the owner on Mar 18, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions migrations/Migration20241206091921.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Ref, ref } from '@mikro-orm/core';

import { User } from '@/users/entities/user.entity';
import { OrganizationUser } from '@/administration/entities/organization-user.entity';
import { Project, ProjectVisiblity } from '@/administration/entities/project.entity';
import { Project } from '@/administration/entities/project.entity';
import { Organization } from '@/administration/entities/organization.entity';
import { UserPrincipal } from '@/administration/entities/principals/user-principal.entity';
import { ProjectPrincipal } from '@/administration/entities/project-principal.entity';
Expand Down Expand Up @@ -49,8 +49,7 @@ export class Migration20241206091921 extends Migration {
const project = new Project({
name: `${user.name}'s project`,
organization: ref(Organization, user.defaultOrganization),
createdBy: ref(OrganizationUser, organizationUser._id),
visibility: ProjectVisiblity.PRIVATE
createdBy: ref(OrganizationUser, organizationUser._id)
});
await this.getCollection<BaseDocument>(Project).insertOne(
{
Expand All @@ -60,7 +59,6 @@ export class Migration20241206091921 extends Migration {
organization: project.organization.id,
createdBy: project.createdBy.id,
name: project.name,
visibility: project.visibility,
status: project.status
},
{ session: this.ctx }
Expand Down
13 changes: 13 additions & 0 deletions migrations/Migration20250110114435.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Migration } from '@mikro-orm/migrations-mongodb';

import { Project } from '@/administration/entities/project.entity';

export class Migration20250110114435 extends Migration {
async up(): Promise<void> {
await this.getCollection(Project).updateMany(
{},
{ $unset: { visibility: '' } },
{ session: this.ctx }
);
}
}
9 changes: 1 addition & 8 deletions src/administration/dtos/project-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,14 @@

import { FromSchema, JSONSchema } from 'json-schema-to-ts';

import { ProjectVisiblity } from '../entities/project.entity.js';

import { projectSchema } from './project.js';

export const projectCreateBodySchema = {
type: 'object',
additionalProperties: false,
required: ['name'],
properties: {
name: { type: 'string' },
visibility: {
type: 'string',
enum: Object.values(ProjectVisiblity),
default: ProjectVisiblity.PUBLIC
}
name: { type: 'string' }
}
} as const satisfies JSONSchema;
export type ProjectCreateBody = FromSchema<typeof projectCreateBodySchema>;
Expand Down
8 changes: 1 addition & 7 deletions src/administration/dtos/project-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

import { FromSchema, JSONSchema } from 'json-schema-to-ts';

import { ProjectVisiblity } from '../entities/project.entity.js';

import { projectSchema } from './project.js';
import { projectReadParamsSchema } from './project-read.js';

Expand All @@ -28,11 +26,7 @@ export const projectUpdateBodySchema = {
type: 'object',
additionalProperties: false,
properties: {
name: { type: 'string' },
visibility: {
type: 'string',
enum: Object.values(ProjectVisiblity)
}
name: { type: 'string' }
}
} as const satisfies JSONSchema;
export type ProjectUpdateBody = FromSchema<typeof projectUpdateBodySchema>;
Expand Down
5 changes: 2 additions & 3 deletions src/administration/dtos/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@

import { FromSchema, JSONSchema } from 'json-schema-to-ts';

import { ProjectStatus, ProjectVisiblity } from '../entities/project.entity';
import { ProjectStatus } from '../entities/project.entity';

export const projectSchema = {
type: 'object',
required: ['object', 'id', 'name', 'visibility', 'status', 'created_at', 'archived_at'],
required: ['object', 'id', 'name', 'status', 'created_at', 'archived_at'],
properties: {
object: { const: 'organization.project' },
id: { type: 'string' },
name: { type: 'string' },
visibility: { type: 'string', enum: Object.values(ProjectVisiblity) },
status: { type: 'string', enum: Object.values(ProjectStatus) },
created_at: { type: 'number' },
archived_at: { type: 'number', nullable: true }
Expand Down
19 changes: 2 additions & 17 deletions src/administration/entities/project.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ export const ProjectStatus = {
} as const;
export type ProjectStatus = (typeof ProjectStatus)[keyof typeof ProjectStatus];

export const ProjectVisiblity = {
PUBLIC: 'public',
PRIVATE: 'private'
} as const;
export type ProjectVisiblity = (typeof ProjectVisiblity)[keyof typeof ProjectVisiblity];

@Entity()
export class Project extends OrganizationAdministrationScopedEntity {
getIdPrefix(): string {
Expand All @@ -53,20 +47,11 @@ export class Project extends OrganizationAdministrationScopedEntity {
@Property()
archivedAt?: Date;

@Enum(() => ProjectVisiblity)
visibility: ProjectVisiblity;

constructor({
name,
status = ProjectStatus.ACTIVE,
visibility = ProjectVisiblity.PUBLIC,
...rest
}: ProjectInput) {
constructor({ name, status = ProjectStatus.ACTIVE, ...rest }: ProjectInput) {
super(rest);

this.name = name;
this.status = status;
this.visibility = visibility;
}

override delete(): void {
Expand Down Expand Up @@ -94,4 +79,4 @@ export class Project extends OrganizationAdministrationScopedEntity {

export type ProjectInput = OrganizationAdministrationScopedEntityInput &
Pick<Project, 'name'> &
Pick<Partial<Project>, 'status' | 'visibility'>;
Pick<Partial<Project>, 'status'>;
32 changes: 6 additions & 26 deletions src/administration/projects.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import { requestContext } from '@fastify/request-context';
import dayjs from 'dayjs';

import { ProjectCreateBody, ProjectCreateResponse } from './dtos/project-create';
import { Project, ProjectStatus, ProjectVisiblity } from './entities/project.entity';
import { Project, ProjectStatus } from './entities/project.entity';
import { Project as ProjectDto } from './dtos/project';
import { ProjectsListQuery, ProjectsListResponse } from './dtos/projects-list';
import { ProjectPrincipal } from './entities/project-principal.entity';
import { UserPrincipal } from './entities/principals/user-principal.entity';
import { OrganizationUserRole, ProjectRole } from './entities/constants';
import { ProjectRole } from './entities/constants';
import { getOrganizationUser } from './helpers';
import { ProjectReadParams, ProjectReadResponse } from './dtos/project-read';
import {
Expand All @@ -46,27 +46,16 @@ export function toDto(project: Loaded<Project>): ProjectDto {
object: 'organization.project',
id: project.id,
name: project.name,
visibility: project.visibility,
status: project.status,
created_at: dayjs(project.createdAt).unix(),
archived_at: project.archivedAt ? dayjs(project.archivedAt).unix() : null
};
}

export async function createProject({
name,
visibility
}: ProjectCreateBody): Promise<ProjectCreateResponse> {
export async function createProject({ name }: ProjectCreateBody): Promise<ProjectCreateResponse> {
const orgUser = getOrganizationUser();

if (orgUser.role === OrganizationUserRole.MEMBER && visibility === ProjectVisiblity.PUBLIC) {
throw new APIError({
message: 'Members can only create private projects',
code: APIErrorCode.INVALID_INPUT
});
}

const project = new Project({ name, visibility });
const project = new Project({ name });
const projectPrincipal = new ProjectPrincipal({
project: ref(project),
createdBy: ORM.em
Expand All @@ -92,8 +81,7 @@ export async function readProject({ project_id }: ProjectReadParams): Promise<Pr

export async function updateProject({
project_id,
name,
visibility
name
}: ProjectUpdateParams & ProjectUpdateBody): Promise<ProjectUpdateResponse> {
const project = await ORM.em.getRepository(Project).findOneOrFail({ id: project_id });

Expand All @@ -104,7 +92,6 @@ export async function updateProject({
});

project.name = getUpdatedValue(name, project.name);
project.visibility = getUpdatedValue(visibility, project.visibility);
await ORM.em.flush();

return toDto(project);
Expand All @@ -127,14 +114,7 @@ export async function listProjects({
); // TODO missing pagination

const filter: FilterQuery<Project> = {
$and: [
{
$or: [
{ id: { $in: principals.map(({ project }) => project.id) } },
{ visibility: ProjectVisiblity.PUBLIC }
]
}
]
id: { $in: principals.map(({ project }) => project.id) }
};

if (!include_archived) {
Expand Down
2 changes: 1 addition & 1 deletion src/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export async function createUser({
requestContext.set('organizationUser', orgUser);
}

const project = new Project({ name: `${name}'s project`, visibility: 'private' });
const project = new Project({ name: `${name}'s project` });
const projectPrincipal = new ProjectPrincipal({
project: ref(project),
createdBy: ORM.em
Expand Down