feat: groups

This commit is contained in:
Jason Rasmussen
2025-07-30 18:18:38 -04:00
parent 641a3baadd
commit 4a881022c3
76 changed files with 6515 additions and 124 deletions
+56
View File
@@ -0,0 +1,56 @@
import { Type } from 'class-transformer';
import { IsArray, ValidateNested } from 'class-validator';
import { Group } from 'src/database';
import { GroupResponseDto, mapGroup } from 'src/dtos/group.dto';
import { AlbumUserRole } from 'src/enum';
import { ValidateEnum, ValidateUUID } from 'src/validation';
export class AlbumGroupCreateAllDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => AlbumGroupDto)
groups!: AlbumGroupDto[];
}
export class AlbumGroupDeleteAllDto {
@ValidateUUID({ each: true })
groupIds!: string[];
}
export class AlbumGroupDto {
@ValidateUUID()
groupId!: string;
@ValidateEnum({ enum: AlbumUserRole, name: 'AlbumUserRole', optional: true })
role?: AlbumUserRole;
}
export class AlbumGroupUpdateDto {
@ValidateEnum({ enum: AlbumUserRole, name: 'AlbumUserRole' })
role!: AlbumUserRole;
}
export class AlbumGroupResponseDto extends GroupResponseDto {
metadata!: AlbumGroupMetadata;
}
export class AlbumGroupMetadata {
createdAt!: Date;
updatedAt!: Date;
}
type AlbumGroup = {
createdAt: Date;
updatedAt: Date;
group: Group;
};
export const mapAlbumGroup = (albumGroup: AlbumGroup): AlbumGroupResponseDto => {
return {
...mapGroup(albumGroup.group),
metadata: {
createdAt: albumGroup.createdAt,
updatedAt: albumGroup.updatedAt,
},
};
};
+8 -1
View File
@@ -3,9 +3,10 @@ import { Type } from 'class-transformer';
import { ArrayNotEmpty, IsArray, IsString, ValidateNested } from 'class-validator';
import _ from 'lodash';
import { AlbumUser, AuthSharedLink, User } from 'src/database';
import { AlbumGroupDto } from 'src/dtos/album-group.dto';
import { AssetResponseDto, MapAsset, mapAsset } from 'src/dtos/asset-response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
import { mapUser, UserResponseDto } from 'src/dtos/user.dto';
import { AlbumUserRole, AssetOrder } from 'src/enum';
import { Optional, ValidateBoolean, ValidateEnum, ValidateUUID } from 'src/validation';
@@ -50,6 +51,12 @@ export class CreateAlbumDto {
@Type(() => AlbumUserCreateDto)
albumUsers?: AlbumUserCreateDto[];
@Optional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AlbumGroupDto)
groups?: AlbumGroupDto[];
@ValidateUUID({ optional: true, each: true })
assetIds?: string[];
}
+46
View File
@@ -0,0 +1,46 @@
import { ArrayNotEmpty } from 'class-validator';
import { User } from 'src/database';
import { mapUser, UserResponseDto } from 'src/dtos/user.dto';
import { ValidateUUID } from 'src/validation';
export class GroupUserCreateAllDto {
@ArrayNotEmpty()
users!: GroupUserDto[];
}
export class GroupUserDeleteAllDto {
@ValidateUUID({ each: true })
userIds!: string[];
}
export class GroupUserDto {
@ValidateUUID()
userId!: string;
// TODO potentially add a role UserGroupRole field here
}
export class GroupUserResponseDto extends UserResponseDto {
metadata!: GroupUserMetadata;
}
export class GroupUserMetadata {
createdAt!: Date;
updatedAt!: Date;
}
type GroupUser = {
createdAt: Date;
updatedAt: Date;
user: User;
};
export const mapGroupUser = (groupUser: GroupUser): GroupUserResponseDto => {
return {
...mapUser(groupUser.user),
metadata: {
createdAt: groupUser.createdAt,
updatedAt: groupUser.updatedAt,
},
};
};
+69
View File
@@ -0,0 +1,69 @@
import { Type } from 'class-transformer';
import { IsArray, IsNotEmpty, IsString, ValidateNested } from 'class-validator';
import { Group, GroupAdmin } from 'src/database';
import { GroupUserDto } from 'src/dtos/group-user.dto';
import { Optional, ValidateUUID } from 'src/validation';
export class GroupAdminSearchDto {
@ValidateUUID({ optional: true })
id?: string;
@ValidateUUID({ optional: true })
userId?: string;
}
export class GroupAdminCreateDto {
@IsString()
@IsNotEmpty()
name!: string;
@Optional({ nullable: true, emptyToNull: true })
@IsNotEmpty()
@IsString()
description?: string | null;
@Optional()
@ValidateNested({ each: true })
@Type(() => GroupUserDto)
@IsArray()
users?: GroupUserDto[];
}
export class GroupAdminUpdateDto {
@Optional()
@IsString()
@IsNotEmpty()
name?: string;
@Optional({ nullable: true, emptyToNull: true })
@IsNotEmpty()
@IsString()
description?: string | null;
}
export class GroupResponseDto {
id!: string;
name!: string;
description!: string | null;
}
export class GroupAdminResponseDto extends GroupResponseDto {
createdAt!: Date;
updatedAt!: Date;
}
export const mapGroup = (group: Group | GroupAdmin) => {
return {
id: group.id,
name: group.name,
description: group.description,
};
};
export const mapGroupAdmin = (group: GroupAdmin) => {
return {
...mapGroup(group),
createdAt: group.createdAt,
updatedAt: group.updatedAt,
};
};