refactor(server): auth dto (#5593)

* refactor: AuthUserDto => AuthDto

* refactor: reorganize auth-dto

* refactor: AuthUser() => Auth()
This commit is contained in:
Jason Rasmussen
2023-12-09 23:34:12 -05:00
committed by GitHub
parent 8057c375ba
commit 33529d1d9b
60 changed files with 1033 additions and 1065 deletions

View File

@@ -48,9 +48,9 @@ describe(AlbumService.name, () => {
notShared: 0,
});
expect(albumMock.getOwned).toHaveBeenCalledWith(authStub.admin.id);
expect(albumMock.getShared).toHaveBeenCalledWith(authStub.admin.id);
expect(albumMock.getNotShared).toHaveBeenCalledWith(authStub.admin.id);
expect(albumMock.getOwned).toHaveBeenCalledWith(authStub.admin.user.id);
expect(albumMock.getShared).toHaveBeenCalledWith(authStub.admin.user.id);
expect(albumMock.getNotShared).toHaveBeenCalledWith(authStub.admin.user.id);
});
});
@@ -188,7 +188,7 @@ describe(AlbumService.name, () => {
});
expect(albumMock.create).toHaveBeenCalledWith({
ownerId: authStub.admin.id,
ownerId: authStub.admin.user.id,
albumName: albumStub.empty.albumName,
description: albumStub.empty.description,
sharedUsers: [{ id: 'user-id' }],
@@ -312,7 +312,7 @@ describe(AlbumService.name, () => {
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set([albumStub.sharedWithAdmin.id]));
albumMock.getById.mockResolvedValue(albumStub.sharedWithAdmin);
await expect(
sut.addUsers(authStub.user1, albumStub.sharedWithAdmin.id, { sharedUserIds: [authStub.admin.id] }),
sut.addUsers(authStub.user1, albumStub.sharedWithAdmin.id, { sharedUserIds: [authStub.admin.user.id] }),
).rejects.toBeInstanceOf(BadRequestException);
expect(albumMock.update).not.toHaveBeenCalled();
});
@@ -332,11 +332,11 @@ describe(AlbumService.name, () => {
albumMock.getById.mockResolvedValue(_.cloneDeep(albumStub.sharedWithAdmin));
albumMock.update.mockResolvedValue(albumStub.sharedWithAdmin);
userMock.get.mockResolvedValue(userStub.user2);
await sut.addUsers(authStub.user1, albumStub.sharedWithAdmin.id, { sharedUserIds: [authStub.user2.id] });
await sut.addUsers(authStub.user1, albumStub.sharedWithAdmin.id, { sharedUserIds: [authStub.user2.user.id] });
expect(albumMock.update).toHaveBeenCalledWith({
id: albumStub.sharedWithAdmin.id,
updatedAt: expect.any(Date),
sharedUsers: [userStub.admin, { id: authStub.user2.id }],
sharedUsers: [userStub.admin, { id: authStub.user2.user.id }],
});
});
});
@@ -370,12 +370,12 @@ describe(AlbumService.name, () => {
albumMock.getById.mockResolvedValue(albumStub.sharedWithMultiple);
await expect(
sut.removeUser(authStub.user1, albumStub.sharedWithMultiple.id, authStub.user2.id),
sut.removeUser(authStub.user1, albumStub.sharedWithMultiple.id, authStub.user2.user.id),
).rejects.toBeInstanceOf(BadRequestException);
expect(albumMock.update).not.toHaveBeenCalled();
expect(accessMock.album.checkOwnerAccess).toHaveBeenCalledWith(
authStub.user1.id,
authStub.user1.user.id,
new Set([albumStub.sharedWithMultiple.id]),
);
});
@@ -383,7 +383,7 @@ describe(AlbumService.name, () => {
it('should allow a shared user to remove themselves', async () => {
albumMock.getById.mockResolvedValue(albumStub.sharedWithUser);
await sut.removeUser(authStub.user1, albumStub.sharedWithUser.id, authStub.user1.id);
await sut.removeUser(authStub.user1, albumStub.sharedWithUser.id, authStub.user1.user.id);
expect(albumMock.update).toHaveBeenCalledTimes(1);
expect(albumMock.update).toHaveBeenCalledWith({
@@ -409,7 +409,7 @@ describe(AlbumService.name, () => {
it('should not allow the owner to be removed', async () => {
albumMock.getById.mockResolvedValue(albumStub.empty);
await expect(sut.removeUser(authStub.admin, albumStub.empty.id, authStub.admin.id)).rejects.toBeInstanceOf(
await expect(sut.removeUser(authStub.admin, albumStub.empty.id, authStub.admin.user.id)).rejects.toBeInstanceOf(
BadRequestException,
);
@@ -444,7 +444,7 @@ describe(AlbumService.name, () => {
expect(albumMock.getById).toHaveBeenCalledWith(albumStub.oneAsset.id, { withAssets: true });
expect(accessMock.album.checkOwnerAccess).toHaveBeenCalledWith(
authStub.admin.id,
authStub.admin.user.id,
new Set([albumStub.oneAsset.id]),
);
});
@@ -465,7 +465,7 @@ describe(AlbumService.name, () => {
expect(albumMock.getById).toHaveBeenCalledWith('album-123', { withAssets: true });
expect(accessMock.album.checkSharedLinkAccess).toHaveBeenCalledWith(
authStub.adminSharedLink.sharedLinkId,
authStub.adminSharedLink.sharedLink?.id,
new Set(['album-123']),
);
});
@@ -485,14 +485,20 @@ describe(AlbumService.name, () => {
await sut.get(authStub.user1, 'album-123', {});
expect(albumMock.getById).toHaveBeenCalledWith('album-123', { withAssets: true });
expect(accessMock.album.checkSharedAlbumAccess).toHaveBeenCalledWith(authStub.user1.id, new Set(['album-123']));
expect(accessMock.album.checkSharedAlbumAccess).toHaveBeenCalledWith(
authStub.user1.user.id,
new Set(['album-123']),
);
});
it('should throw an error for no access', async () => {
await expect(sut.get(authStub.admin, 'album-123', {})).rejects.toBeInstanceOf(BadRequestException);
expect(accessMock.album.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.id, new Set(['album-123']));
expect(accessMock.album.checkSharedAlbumAccess).toHaveBeenCalledWith(authStub.admin.id, new Set(['album-123']));
expect(accessMock.album.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['album-123']));
expect(accessMock.album.checkSharedAlbumAccess).toHaveBeenCalledWith(
authStub.admin.user.id,
new Set(['album-123']),
);
});
});
@@ -590,7 +596,7 @@ describe(AlbumService.name, () => {
});
expect(accessMock.album.checkSharedLinkAccess).toHaveBeenCalledWith(
authStub.adminSharedLink.sharedLinkId,
authStub.adminSharedLink.sharedLink?.id,
new Set(['album-123']),
);
});
@@ -610,7 +616,7 @@ describe(AlbumService.name, () => {
updatedAt: expect.any(Date),
albumThumbnailAssetId: 'asset-1',
});
expect(accessMock.asset.checkPartnerAccess).toHaveBeenCalledWith(authStub.admin.id, new Set(['asset-1']));
expect(accessMock.asset.checkPartnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['asset-1']));
});
it('should skip duplicate assets', async () => {
@@ -635,8 +641,8 @@ describe(AlbumService.name, () => {
{ success: false, id: 'asset-1', error: BulkIdErrorReason.NO_PERMISSION },
]);
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.id, new Set(['asset-1']));
expect(accessMock.asset.checkPartnerAccess).toHaveBeenCalledWith(authStub.admin.id, new Set(['asset-1']));
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['asset-1']));
expect(accessMock.asset.checkPartnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['asset-1']));
});
it('should not allow unauthorized access to the album', async () => {
@@ -729,7 +735,7 @@ describe(AlbumService.name, () => {
// // await expect(
// // sut.removeAssetsFromAlbum(
// // authUser,
// // auth,
// // {
// // ids: ['1'],
// // },
@@ -755,6 +761,6 @@ describe(AlbumService.name, () => {
// albumRepositoryMock.get.mockImplementation(() => Promise.resolve<AlbumEntity>(albumEntity));
// albumRepositoryMock.addAssets.mockImplementation(() => Promise.resolve<AddAssetsResponseDto>(albumResponse));
// await expect(sut.removeAssets(authUser, albumId, { ids: ['1'] })).rejects.toBeInstanceOf(ForbiddenException);
// await expect(sut.removeAssets(auth, albumId, { ids: ['1'] })).rejects.toBeInstanceOf(ForbiddenException);
// });
});

View File

@@ -2,7 +2,7 @@ import { AlbumEntity, AssetEntity, UserEntity } from '@app/infra/entities';
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { AccessCore, Permission } from '../access';
import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from '../asset';
import { AuthUserDto } from '../auth';
import { AuthDto } from '../auth';
import { setUnion } from '../domain.util';
import {
AlbumAssetCount,
@@ -35,11 +35,11 @@ export class AlbumService {
this.access = AccessCore.create(accessRepository);
}
async getCount(authUser: AuthUserDto): Promise<AlbumCountResponseDto> {
async getCount(auth: AuthDto): Promise<AlbumCountResponseDto> {
const [owned, shared, notShared] = await Promise.all([
this.albumRepository.getOwned(authUser.id),
this.albumRepository.getShared(authUser.id),
this.albumRepository.getNotShared(authUser.id),
this.albumRepository.getOwned(auth.user.id),
this.albumRepository.getShared(auth.user.id),
this.albumRepository.getNotShared(auth.user.id),
]);
return {
@@ -49,7 +49,7 @@ export class AlbumService {
};
}
async getAll({ id: ownerId }: AuthUserDto, { assetId, shared }: GetAlbumsDto): Promise<AlbumResponseDto[]> {
async getAll({ user: { id: ownerId } }: AuthDto, { assetId, shared }: GetAlbumsDto): Promise<AlbumResponseDto[]> {
const invalidAlbumIds = await this.albumRepository.getInvalidThumbnail();
for (const albumId of invalidAlbumIds) {
const newThumbnail = await this.assetRepository.getFirstAssetForAlbumId(albumId);
@@ -98,8 +98,8 @@ export class AlbumService {
);
}
async get(authUser: AuthUserDto, id: string, dto: AlbumInfoDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(authUser, Permission.ALBUM_READ, id);
async get(auth: AuthDto, id: string, dto: AlbumInfoDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(auth, Permission.ALBUM_READ, id);
await this.albumRepository.updateThumbnails();
const withAssets = dto.withoutAssets === undefined ? true : !dto.withoutAssets;
const album = await this.findOrFail(id, { withAssets });
@@ -113,7 +113,7 @@ export class AlbumService {
};
}
async create(authUser: AuthUserDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
async create(auth: AuthDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
for (const userId of dto.sharedWithUserIds || []) {
const exists = await this.userRepository.get(userId, {});
if (!exists) {
@@ -122,7 +122,7 @@ export class AlbumService {
}
const album = await this.albumRepository.create({
ownerId: authUser.id,
ownerId: auth.user.id,
albumName: dto.albumName,
description: dto.description,
sharedUsers: dto.sharedWithUserIds?.map((value) => ({ id: value }) as UserEntity) ?? [],
@@ -133,8 +133,8 @@ export class AlbumService {
return mapAlbumWithAssets(album);
}
async update(authUser: AuthUserDto, id: string, dto: UpdateAlbumDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(authUser, Permission.ALBUM_UPDATE, id);
async update(auth: AuthDto, id: string, dto: UpdateAlbumDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(auth, Permission.ALBUM_UPDATE, id);
const album = await this.findOrFail(id, { withAssets: true });
@@ -155,22 +155,22 @@ export class AlbumService {
return mapAlbumWithoutAssets(updatedAlbum);
}
async delete(authUser: AuthUserDto, id: string): Promise<void> {
await this.access.requirePermission(authUser, Permission.ALBUM_DELETE, id);
async delete(auth: AuthDto, id: string): Promise<void> {
await this.access.requirePermission(auth, Permission.ALBUM_DELETE, id);
const album = await this.findOrFail(id, { withAssets: false });
await this.albumRepository.delete(album);
}
async addAssets(authUser: AuthUserDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
const album = await this.findOrFail(id, { withAssets: false });
await this.access.requirePermission(authUser, Permission.ALBUM_READ, id);
await this.access.requirePermission(auth, Permission.ALBUM_READ, id);
const existingAssetIds = await this.albumRepository.getAssetIds(id, dto.ids);
const notPresentAssetIds = dto.ids.filter((id) => !existingAssetIds.has(id));
const allowedAssetIds = await this.access.checkAccess(authUser, Permission.ASSET_SHARE, notPresentAssetIds);
const allowedAssetIds = await this.access.checkAccess(auth, Permission.ASSET_SHARE, notPresentAssetIds);
const results: BulkIdResponseDto[] = [];
for (const assetId of dto.ids) {
@@ -202,14 +202,14 @@ export class AlbumService {
return results;
}
async removeAssets(authUser: AuthUserDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
const album = await this.findOrFail(id, { withAssets: false });
await this.access.requirePermission(authUser, Permission.ALBUM_READ, id);
await this.access.requirePermission(auth, Permission.ALBUM_READ, id);
const existingAssetIds = await this.albumRepository.getAssetIds(id, dto.ids);
const canRemove = await this.access.checkAccess(authUser, Permission.ALBUM_REMOVE_ASSET, existingAssetIds);
const canShare = await this.access.checkAccess(authUser, Permission.ASSET_SHARE, existingAssetIds);
const canRemove = await this.access.checkAccess(auth, Permission.ALBUM_REMOVE_ASSET, existingAssetIds);
const canShare = await this.access.checkAccess(auth, Permission.ASSET_SHARE, existingAssetIds);
const allowedAssetIds = setUnion(canRemove, canShare);
const results: BulkIdResponseDto[] = [];
@@ -241,8 +241,8 @@ export class AlbumService {
return results;
}
async addUsers(authUser: AuthUserDto, id: string, dto: AddUsersDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(authUser, Permission.ALBUM_SHARE, id);
async addUsers(auth: AuthDto, id: string, dto: AddUsersDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(auth, Permission.ALBUM_SHARE, id);
const album = await this.findOrFail(id, { withAssets: false });
@@ -273,9 +273,9 @@ export class AlbumService {
.then(mapAlbumWithoutAssets);
}
async removeUser(authUser: AuthUserDto, id: string, userId: string | 'me'): Promise<void> {
async removeUser(auth: AuthDto, id: string, userId: string | 'me'): Promise<void> {
if (userId === 'me') {
userId = authUser.id;
userId = auth.user.id;
}
const album = await this.findOrFail(id, { withAssets: false });
@@ -290,8 +290,8 @@ export class AlbumService {
}
// non-admin can remove themselves
if (authUser.id !== userId) {
await this.access.requirePermission(authUser, Permission.ALBUM_SHARE, id);
if (auth.user.id !== userId) {
await this.access.requirePermission(auth, Permission.ALBUM_SHARE, id);
}
await this.albumRepository.update({