1
0
mirror of https://github.com/immich-app/immich.git synced 2024-11-28 09:33:27 +02:00

refactor(server): domain/infra (#1298)

* refactor: user repository

* refactor: user module

* refactor: move database into infra

* refactor(cli): use user core

* chore: import path

* chore: tests
This commit is contained in:
Jason Rasmussen 2023-01-11 21:34:36 -05:00 committed by GitHub
parent 89a6ed2a5b
commit 131caa20eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
182 changed files with 701 additions and 676 deletions

View File

@ -1,11 +1,17 @@
import { DatabaseModule, SystemConfigEntity, UserEntity } from '@app/database'; import { DomainModule } from '@app/domain';
import { InfraModule, SystemConfigEntity } from '@app/infra';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from './commands/password-login'; import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from './commands/password-login';
import { PromptPasswordQuestions, ResetAdminPasswordCommand } from './commands/reset-admin-password.command'; import { PromptPasswordQuestions, ResetAdminPasswordCommand } from './commands/reset-admin-password.command';
@Module({ @Module({
imports: [DatabaseModule, TypeOrmModule.forFeature([UserEntity, SystemConfigEntity])], imports: [
DomainModule.register({
imports: [InfraModule],
}),
TypeOrmModule.forFeature([SystemConfigEntity]),
],
providers: [ providers: [
ResetAdminPasswordCommand, ResetAdminPasswordCommand,
PromptPasswordQuestions, PromptPasswordQuestions,

View File

@ -1,4 +1,4 @@
import { SystemConfigEntity, SystemConfigKey } from '@app/database'; import { SystemConfigEntity, SystemConfigKey } from '@app/infra';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import axios from 'axios'; import axios from 'axios';
import { Command, CommandRunner } from 'nest-commander'; import { Command, CommandRunner } from 'nest-commander';
@ -9,9 +9,7 @@ import { Repository } from 'typeorm';
description: 'Enable password login', description: 'Enable password login',
}) })
export class EnablePasswordLoginCommand extends CommandRunner { export class EnablePasswordLoginCommand extends CommandRunner {
constructor( constructor(@InjectRepository(SystemConfigEntity) private repository: Repository<SystemConfigEntity>) {
@InjectRepository(SystemConfigEntity) private repository: Repository<SystemConfigEntity>, //
) {
super(); super();
} }

View File

@ -1,40 +1,38 @@
import { UserEntity } from '@app/database'; import { Inject } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import bcrypt from 'bcrypt';
import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander'; import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander';
import { randomBytes } from 'node:crypto'; import { randomBytes } from 'node:crypto';
import { Repository } from 'typeorm'; import { IUserRepository, UserCore } from '@app/domain';
@Command({ @Command({
name: 'reset-admin-password', name: 'reset-admin-password',
description: 'Reset the admin password', description: 'Reset the admin password',
}) })
export class ResetAdminPasswordCommand extends CommandRunner { export class ResetAdminPasswordCommand extends CommandRunner {
constructor( userCore: UserCore;
private readonly inquirer: InquirerService,
@InjectRepository(UserEntity) private userRepository: Repository<UserEntity>, constructor(private readonly inquirer: InquirerService, @Inject(IUserRepository) userRepository: IUserRepository) {
) {
super(); super();
this.userCore = new UserCore(userRepository);
} }
async run(): Promise<void> { async run(): Promise<void> {
let { password } = await this.inquirer.ask<{ password: string }>('prompt-password', undefined); const user = await this.userCore.getAdmin();
password = password || randomBytes(24).toString('base64').replace(/\W/g, '');
const hashedPassword = await bcrypt.hash(password, 10);
const user = await this.userRepository.findOne({ where: { isAdmin: true } });
if (!user) { if (!user) {
console.log('Unable to reset password: no admin user.'); console.log('Unable to reset password: no admin user.');
return; return;
} }
user.password = hashedPassword; const { password: providedPassword } = await this.inquirer.ask<{ password: string }>('prompt-password', undefined);
user.shouldChangePassword = true; const password = providedPassword || randomBytes(24).toString('base64').replace(/\W/g, '');
await this.userRepository.save(user); await this.userCore.updateUser(user, user.id, { password });
console.log(`New password:\n${password}`); if (providedPassword) {
console.log('The admin password has been updated.');
} else {
console.log(`The admin password has been updated to:\n${password}`);
}
} }
} }

View File

@ -1,4 +1,4 @@
import { AlbumEntity, AssetAlbumEntity, UserAlbumEntity } from '@app/database'; import { AlbumEntity, AssetAlbumEntity, UserAlbumEntity } from '@app/infra';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository, SelectQueryBuilder, DataSource, Brackets, Not, IsNull } from 'typeorm'; import { In, Repository, SelectQueryBuilder, DataSource, Brackets, Not, IsNull } from 'typeorm';

View File

@ -2,11 +2,10 @@ import { forwardRef, Module } from '@nestjs/common';
import { AlbumService } from './album.service'; import { AlbumService } from './album.service';
import { AlbumController } from './album.controller'; import { AlbumController } from './album.controller';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { AlbumEntity, AssetAlbumEntity, UserAlbumEntity } from '@app/database'; import { AlbumEntity, AssetAlbumEntity, UserAlbumEntity } from '@app/infra';
import { AlbumRepository, IAlbumRepository } from './album-repository'; import { AlbumRepository, IAlbumRepository } from './album-repository';
import { DownloadModule } from '../../modules/download/download.module'; import { DownloadModule } from '../../modules/download/download.module';
import { AssetModule } from '../asset/asset.module'; import { AssetModule } from '../asset/asset.module';
import { UserModule } from '../user/user.module';
import { ShareModule } from '../share/share.module'; import { ShareModule } from '../share/share.module';
const ALBUM_REPOSITORY_PROVIDER = { const ALBUM_REPOSITORY_PROVIDER = {
@ -18,7 +17,6 @@ const ALBUM_REPOSITORY_PROVIDER = {
imports: [ imports: [
TypeOrmModule.forFeature([AlbumEntity, AssetAlbumEntity, UserAlbumEntity]), TypeOrmModule.forFeature([AlbumEntity, AssetAlbumEntity, UserAlbumEntity]),
DownloadModule, DownloadModule,
UserModule,
forwardRef(() => AssetModule), forwardRef(() => AssetModule),
ShareModule, ShareModule,
], ],

View File

@ -1,7 +1,7 @@
import { AlbumService } from './album.service'; import { AlbumService } from './album.service';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common'; import { BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common';
import { AlbumEntity } from '@app/database'; import { AlbumEntity } from '@app/infra';
import { AlbumResponseDto } from './response-dto/album-response.dto'; import { AlbumResponseDto } from './response-dto/album-response.dto';
import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto'; import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto';
import { IAlbumRepository } from './album-repository'; import { IAlbumRepository } from './album-repository';

View File

@ -1,7 +1,7 @@
import { BadRequestException, Inject, Injectable, NotFoundException, ForbiddenException, Logger } from '@nestjs/common'; import { BadRequestException, Inject, Injectable, NotFoundException, ForbiddenException, Logger } from '@nestjs/common';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { CreateAlbumDto } from './dto/create-album.dto'; import { CreateAlbumDto } from './dto/create-album.dto';
import { AlbumEntity, SharedLinkType } from '@app/database'; import { AlbumEntity, SharedLinkType } from '@app/infra';
import { AddUsersDto } from './dto/add-users.dto'; import { AddUsersDto } from './dto/add-users.dto';
import { RemoveAssetsDto } from './dto/remove-assets.dto'; import { RemoveAssetsDto } from './dto/remove-assets.dto';
import { UpdateAlbumDto } from './dto/update-album.dto'; import { UpdateAlbumDto } from './dto/update-album.dto';

View File

@ -1,5 +1,5 @@
import { AlbumEntity } from '@app/database'; import { AlbumEntity } from '@app/infra';
import { UserResponseDto, mapUser } from '../../user/response-dto/user-response.dto'; import { UserResponseDto, mapUser } from '@app/domain';
import { AssetResponseDto, mapAsset } from '../../asset/response-dto/asset-response.dto'; import { AssetResponseDto, mapAsset } from '../../asset/response-dto/asset-response.dto';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';

View File

@ -1,4 +1,4 @@
import { APIKeyEntity } from '@app/database'; import { APIKeyEntity } from '@app/infra';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { APIKeyController } from './api-key.controller'; import { APIKeyController } from './api-key.controller';

View File

@ -1,4 +1,4 @@
import { APIKeyEntity } from '@app/database'; import { APIKeyEntity } from '@app/infra';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { BadRequestException, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; import { BadRequestException, Inject, Injectable, UnauthorizedException } from '@nestjs/common';
import { compareSync, hash } from 'bcrypt'; import { compareSync, hash } from 'bcrypt';
import { randomBytes } from 'node:crypto'; import { randomBytes } from 'node:crypto';

View File

@ -1,4 +1,4 @@
import { APIKeyEntity } from '@app/database'; import { APIKeyEntity } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
export class APIKeyResponseDto { export class APIKeyResponseDto {

View File

@ -1,6 +1,6 @@
import { SearchPropertiesDto } from './dto/search-properties.dto'; import { SearchPropertiesDto } from './dto/search-properties.dto';
import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto'; import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto';
import { AssetEntity, AssetType } from '@app/database'; import { AssetEntity, AssetType } from '@app/infra';
import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm/repository/Repository'; import { Repository } from 'typeorm/repository/Repository';

View File

@ -2,7 +2,7 @@ import { forwardRef, Module } from '@nestjs/common';
import { AssetService } from './asset.service'; import { AssetService } from './asset.service';
import { AssetController } from './asset.controller'; import { AssetController } from './asset.controller';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { BackgroundTaskModule } from '../../modules/background-task/background-task.module'; import { BackgroundTaskModule } from '../../modules/background-task/background-task.module';
import { BackgroundTaskService } from '../../modules/background-task/background-task.service'; import { BackgroundTaskService } from '../../modules/background-task/background-task.service';
@ -11,7 +11,6 @@ import { AssetRepository, IAssetRepository } from './asset-repository';
import { DownloadModule } from '../../modules/download/download.module'; import { DownloadModule } from '../../modules/download/download.module';
import { TagModule } from '../tag/tag.module'; import { TagModule } from '../tag/tag.module';
import { AlbumModule } from '../album/album.module'; import { AlbumModule } from '../album/album.module';
import { UserModule } from '../user/user.module';
import { StorageModule } from '@app/storage'; import { StorageModule } from '@app/storage';
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant'; import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
import { ShareModule } from '../share/share.module'; import { ShareModule } from '../share/share.module';
@ -27,7 +26,6 @@ const ASSET_REPOSITORY_PROVIDER = {
CommunicationModule, CommunicationModule,
BackgroundTaskModule, BackgroundTaskModule,
DownloadModule, DownloadModule,
UserModule,
AlbumModule, AlbumModule,
TagModule, TagModule,
StorageModule, StorageModule,

View File

@ -2,7 +2,7 @@ import { IAssetRepository } from './asset-repository';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { AssetService } from './asset.service'; import { AssetService } from './asset.service';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { AssetEntity, AssetType } from '@app/database'; import { AssetEntity, AssetType } from '@app/infra';
import { CreateAssetDto } from './dto/create-asset.dto'; import { CreateAssetDto } from './dto/create-asset.dto';
import { AssetCountByTimeBucket } from './response-dto/asset-count-by-time-group-response.dto'; import { AssetCountByTimeBucket } from './response-dto/asset-count-by-time-group-response.dto';
import { TimeGroupEnum } from './dto/get-asset-count-by-time-bucket.dto'; import { TimeGroupEnum } from './dto/get-asset-count-by-time-bucket.dto';

View File

@ -13,7 +13,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { createHash, randomUUID } from 'node:crypto'; import { createHash, randomUUID } from 'node:crypto';
import { QueryFailedError, Repository } from 'typeorm'; import { QueryFailedError, Repository } from 'typeorm';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { AssetEntity, AssetType } from '@app/database'; import { AssetEntity, AssetType } from '@app/infra';
import { constants, createReadStream, ReadStream, stat } from 'fs'; import { constants, createReadStream, ReadStream, stat } from 'fs';
import { ServeFileDto } from './dto/serve-file.dto'; import { ServeFileDto } from './dto/serve-file.dto';
import { Response as Res } from 'express'; import { Response as Res } from 'express';

View File

@ -1,5 +1,5 @@
import { IsNotEmpty, IsOptional } from 'class-validator'; import { IsNotEmpty, IsOptional } from 'class-validator';
import { AssetType } from '@app/database'; import { AssetType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
export class CreateAssetDto { export class CreateAssetDto {

View File

@ -1,4 +1,4 @@
import { AssetEntity, AssetType } from '@app/database'; import { AssetEntity, AssetType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { mapTag, TagResponseDto } from '../../tag/response-dto/tag-response.dto'; import { mapTag, TagResponseDto } from '../../tag/response-dto/tag-response.dto';
import { ExifResponseDto, mapExif } from './exif-response.dto'; import { ExifResponseDto, mapExif } from './exif-response.dto';

View File

@ -1,4 +1,4 @@
import { ExifEntity } from '@app/database'; import { ExifEntity } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
export class ExifResponseDto { export class ExifResponseDto {

View File

@ -1,4 +1,4 @@
import { SmartInfoEntity } from '@app/database'; import { SmartInfoEntity } from '@app/infra';
export class SmartInfoResponseDto { export class SmartInfoResponseDto {
id?: string; id?: string;

View File

@ -5,7 +5,7 @@ import { AuthType, IMMICH_AUTH_TYPE_COOKIE } from '../../constants/jwt.constant'
import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator'; import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
import { Authenticated } from '../../decorators/authenticated.decorator'; import { Authenticated } from '../../decorators/authenticated.decorator';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { UserResponseDto } from '../user/response-dto/user-response.dto'; import { UserResponseDto } from '@app/domain';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { ChangePasswordDto } from './dto/change-password.dto'; import { ChangePasswordDto } from './dto/change-password.dto';
import { LoginCredentialDto } from './dto/login-credential.dto'; import { LoginCredentialDto } from './dto/login-credential.dto';

View File

@ -2,12 +2,11 @@ import { Module } from '@nestjs/common';
import { ImmichConfigModule } from '@app/immich-config'; import { ImmichConfigModule } from '@app/immich-config';
import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module'; import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module';
import { OAuthModule } from '../oauth/oauth.module'; import { OAuthModule } from '../oauth/oauth.module';
import { UserModule } from '../user/user.module';
import { AuthController } from './auth.controller'; import { AuthController } from './auth.controller';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
@Module({ @Module({
imports: [UserModule, ImmichJwtModule, OAuthModule, ImmichConfigModule], imports: [ImmichJwtModule, OAuthModule, ImmichConfigModule],
controllers: [AuthController], controllers: [AuthController],
providers: [AuthService], providers: [AuthService],
}) })

View File

@ -1,12 +1,12 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { BadRequestException, UnauthorizedException } from '@nestjs/common';
import * as bcrypt from 'bcrypt'; import * as bcrypt from 'bcrypt';
import { SystemConfig } from '@app/database/entities/system-config.entity'; import { SystemConfig } from '@app/infra';
import { ImmichConfigService } from '@app/immich-config'; import { ImmichConfigService } from '@app/immich-config';
import { AuthType } from '../../constants/jwt.constant'; import { AuthType } from '../../constants/jwt.constant';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { OAuthService } from '../oauth/oauth.service'; import { OAuthService } from '../oauth/oauth.service';
import { IUserRepository } from '../user/user-repository'; import { IUserRepository } from '@app/domain';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { SignUpDto } from './dto/sign-up.dto'; import { SignUpDto } from './dto/sign-up.dto';
import { LoginResponseDto } from './response-dto/login-response.dto'; import { LoginResponseDto } from './response-dto/login-response.dto';

View File

@ -7,11 +7,11 @@ import {
UnauthorizedException, UnauthorizedException,
} from '@nestjs/common'; } from '@nestjs/common';
import * as bcrypt from 'bcrypt'; import * as bcrypt from 'bcrypt';
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { AuthType } from '../../constants/jwt.constant'; import { AuthType } from '../../constants/jwt.constant';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { IUserRepository } from '../user/user-repository'; import { IUserRepository } from '@app/domain';
import { ChangePasswordDto } from './dto/change-password.dto'; import { ChangePasswordDto } from './dto/change-password.dto';
import { LoginCredentialDto } from './dto/login-credential.dto'; import { LoginCredentialDto } from './dto/login-credential.dto';
import { SignUpDto } from './dto/sign-up.dto'; import { SignUpDto } from './dto/sign-up.dto';
@ -19,9 +19,9 @@ import { AdminSignupResponseDto, mapAdminSignupResponse } from './response-dto/a
import { LoginResponseDto } from './response-dto/login-response.dto'; import { LoginResponseDto } from './response-dto/login-response.dto';
import { LogoutResponseDto } from './response-dto/logout-response.dto'; import { LogoutResponseDto } from './response-dto/logout-response.dto';
import { OAuthService } from '../oauth/oauth.service'; import { OAuthService } from '../oauth/oauth.service';
import { UserCore } from '../user/user.core'; import { UserCore } from '@app/domain';
import { ImmichConfigService, INITIAL_SYSTEM_CONFIG } from '@app/immich-config'; import { ImmichConfigService, INITIAL_SYSTEM_CONFIG } from '@app/immich-config';
import { SystemConfig } from '@app/database/entities/system-config.entity'; import { SystemConfig } from '@app/infra';
@Injectable() @Injectable()
export class AuthService { export class AuthService {

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
export class AdminSignupResponseDto { export class AdminSignupResponseDto {
id!: string; id!: string;

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { ApiResponseProperty } from '@nestjs/swagger'; import { ApiResponseProperty } from '@nestjs/swagger';
export class LoginResponseDto { export class LoginResponseDto {

View File

@ -3,7 +3,7 @@ import { Socket, Server } from 'socket.io';
import { ImmichJwtService, JwtValidationResult } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService, JwtValidationResult } from '../../modules/immich-jwt/immich-jwt.service';
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import cookieParser from 'cookie'; import cookieParser from 'cookie';
import { IMMICH_ACCESS_COOKIE } from '../../constants/jwt.constant'; import { IMMICH_ACCESS_COOKIE } from '../../constants/jwt.constant';

View File

@ -6,7 +6,7 @@ import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { JwtModule } from '@nestjs/jwt'; import { JwtModule } from '@nestjs/jwt';
import { jwtConfig } from '../../config/jwt.config'; import { jwtConfig } from '../../config/jwt.config';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([UserEntity]), ImmichJwtModule, JwtModule.register(jwtConfig)], imports: [TypeOrmModule.forFeature([UserEntity]), ImmichJwtModule, JwtModule.register(jwtConfig)],

View File

@ -2,7 +2,7 @@ import { Module } from '@nestjs/common';
import { DeviceInfoService } from './device-info.service'; import { DeviceInfoService } from './device-info.service';
import { DeviceInfoController } from './device-info.controller'; import { DeviceInfoController } from './device-info.controller';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { DeviceInfoEntity } from '@app/database'; import { DeviceInfoEntity } from '@app/infra';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([DeviceInfoEntity])], imports: [TypeOrmModule.forFeature([DeviceInfoEntity])],

View File

@ -1,4 +1,4 @@
import { DeviceInfoEntity, DeviceType } from '@app/database'; import { DeviceInfoEntity, DeviceType } from '@app/infra';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { DeviceInfoService } from './device-info.service'; import { DeviceInfoService } from './device-info.service';

View File

@ -1,4 +1,4 @@
import { DeviceInfoEntity } from '@app/database'; import { DeviceInfoEntity } from '@app/infra';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';

View File

@ -1,5 +1,5 @@
import { IsNotEmpty, IsOptional } from 'class-validator'; import { IsNotEmpty, IsOptional } from 'class-validator';
import { DeviceType } from '@app/database'; import { DeviceType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
export class UpsertDeviceInfoDto { export class UpsertDeviceInfoDto {

View File

@ -1,4 +1,4 @@
import { DeviceInfoEntity, DeviceType } from '@app/database'; import { DeviceInfoEntity, DeviceType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
export class DeviceInfoResponseDto { export class DeviceInfoResponseDto {

View File

@ -1,15 +1,11 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { JobService } from './job.service'; import { JobService } from './job.service';
import { JobController } from './job.controller'; import { JobController } from './job.controller';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module'; import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module';
import { JwtModule } from '@nestjs/jwt';
import { jwtConfig } from '../../config/jwt.config';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { ExifEntity } from '@app/database'; import { ExifEntity } from '@app/infra';
import { TagModule } from '../tag/tag.module'; import { TagModule } from '../tag/tag.module';
import { AssetModule } from '../asset/asset.module'; import { AssetModule } from '../asset/asset.module';
import { UserModule } from '../user/user.module';
import { StorageModule } from '@app/storage'; import { StorageModule } from '@app/storage';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
@ -21,12 +17,10 @@ import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.c
ImmichJwtModule, ImmichJwtModule,
TagModule, TagModule,
AssetModule, AssetModule,
UserModule,
JwtModule.register(jwtConfig),
StorageModule, StorageModule,
BullModule.registerQueue(...immichSharedQueues), BullModule.registerQueue(...immichSharedQueues),
], ],
controllers: [JobController], controllers: [JobController],
providers: [JobService, ImmichJwtService], providers: [JobService],
}) })
export class JobModule {} export class JobModule {}

View File

@ -15,7 +15,7 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { AllJobStatusResponseDto } from './response-dto/all-job-status-response.dto'; import { AllJobStatusResponseDto } from './response-dto/all-job-status-response.dto';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { IAssetRepository } from '../asset/asset-repository'; import { IAssetRepository } from '../asset/asset-repository';
import { AssetType } from '@app/database'; import { AssetType } from '@app/infra';
import { GetJobDto, JobId } from './dto/get-job.dto'; import { GetJobDto, JobId } from './dto/get-job.dto';
import { JobStatusResponseDto } from './response-dto/job-status-response.dto'; import { JobStatusResponseDto } from './response-dto/job-status-response.dto';
import { IMachineLearningJob } from '@app/job/interfaces/machine-learning.interface'; import { IMachineLearningJob } from '@app/job/interfaces/machine-learning.interface';

View File

@ -6,7 +6,7 @@ import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
import { Authenticated } from '../../decorators/authenticated.decorator'; import { Authenticated } from '../../decorators/authenticated.decorator';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { LoginResponseDto } from '../auth/response-dto/login-response.dto'; import { LoginResponseDto } from '../auth/response-dto/login-response.dto';
import { UserResponseDto } from '../user/response-dto/user-response.dto'; import { UserResponseDto } from '@app/domain';
import { OAuthCallbackDto } from './dto/oauth-auth-code.dto'; import { OAuthCallbackDto } from './dto/oauth-auth-code.dto';
import { OAuthConfigDto } from './dto/oauth-config.dto'; import { OAuthConfigDto } from './dto/oauth-config.dto';
import { MOBILE_REDIRECT, OAuthService } from './oauth.service'; import { MOBILE_REDIRECT, OAuthService } from './oauth.service';

View File

@ -1,12 +1,11 @@
import { ImmichConfigModule } from '@app/immich-config'; import { ImmichConfigModule } from '@app/immich-config';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module'; import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module';
import { UserModule } from '../user/user.module';
import { OAuthController } from './oauth.controller'; import { OAuthController } from './oauth.controller';
import { OAuthService } from './oauth.service'; import { OAuthService } from './oauth.service';
@Module({ @Module({
imports: [UserModule, ImmichJwtModule, ImmichConfigModule], imports: [ImmichJwtModule, ImmichConfigModule],
controllers: [OAuthController], controllers: [OAuthController],
providers: [OAuthService], providers: [OAuthService],
exports: [OAuthService], exports: [OAuthService],

View File

@ -1,4 +1,4 @@
import { SystemConfig, UserEntity } from '@app/database'; import { SystemConfig, UserEntity } from '@app/infra';
import { ImmichConfigService } from '@app/immich-config'; import { ImmichConfigService } from '@app/immich-config';
import { BadRequestException } from '@nestjs/common'; import { BadRequestException } from '@nestjs/common';
import { generators, Issuer } from 'openid-client'; import { generators, Issuer } from 'openid-client';
@ -6,7 +6,7 @@ import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { LoginResponseDto } from '../auth/response-dto/login-response.dto'; import { LoginResponseDto } from '../auth/response-dto/login-response.dto';
import { OAuthService } from '../oauth/oauth.service'; import { OAuthService } from '../oauth/oauth.service';
import { IUserRepository } from '../user/user-repository'; import { IUserRepository } from '@app/domain';
const email = 'user@immich.com'; const email = 'user@immich.com';
const sub = 'my-auth-user-sub'; const sub = 'my-auth-user-sub';

View File

@ -1,13 +1,11 @@
import { SystemConfig } from '@app/database/entities/system-config.entity'; import { SystemConfig } from '@app/infra';
import { ImmichConfigService, INITIAL_SYSTEM_CONFIG } from '@app/immich-config'; import { ImmichConfigService, INITIAL_SYSTEM_CONFIG } from '@app/immich-config';
import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common'; import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common';
import { ClientMetadata, custom, generators, Issuer, UserinfoResponse } from 'openid-client'; import { ClientMetadata, custom, generators, Issuer, UserinfoResponse } from 'openid-client';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service'; import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { LoginResponseDto } from '../auth/response-dto/login-response.dto'; import { LoginResponseDto } from '../auth/response-dto/login-response.dto';
import { UserResponseDto } from '../user/response-dto/user-response.dto'; import { IUserRepository, UserResponseDto, UserCore } from '@app/domain';
import { IUserRepository } from '../user/user-repository';
import { UserCore } from '../user/user.core';
import { OAuthCallbackDto } from './dto/oauth-auth-code.dto'; import { OAuthCallbackDto } from './dto/oauth-auth-code.dto';
import { OAuthConfigDto } from './dto/oauth-config.dto'; import { OAuthConfigDto } from './dto/oauth-config.dto';
import { OAuthConfigResponseDto } from './response-dto/oauth-config-response.dto'; import { OAuthConfigResponseDto } from './response-dto/oauth-config-response.dto';

View File

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ServerInfoService } from './server-info.service'; import { ServerInfoService } from './server-info.service';
import { ServerInfoController } from './server-info.controller'; import { ServerInfoController } from './server-info.controller';
import { AssetEntity, UserEntity } from '@app/database'; import { AssetEntity, UserEntity } from '@app/infra';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module'; import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module';

View File

@ -4,7 +4,7 @@ import { ServerInfoResponseDto } from './response-dto/server-info-response.dto';
import diskusage from 'diskusage'; import diskusage from 'diskusage';
import { ServerStatsResponseDto } from './response-dto/server-stats-response.dto'; import { ServerStatsResponseDto } from './response-dto/server-stats-response.dto';
import { UsageByUserDto } from './response-dto/usage-by-user-response.dto'; import { UsageByUserDto } from './response-dto/usage-by-user-response.dto';
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { asHumanReadable } from '../../utils/human-readable.util'; import { asHumanReadable } from '../../utils/human-readable.util';

View File

@ -1,5 +1,5 @@
import { AlbumEntity, AssetEntity } from '@app/database'; import { AlbumEntity, AssetEntity } from '@app/infra';
import { SharedLinkType } from '@app/database/entities/shared-link.entity'; import { SharedLinkType } from '@app/infra';
export class CreateSharedLinkDto { export class CreateSharedLinkDto {
description?: string; description?: string;

View File

@ -1,4 +1,4 @@
import { SharedLinkEntity, SharedLinkType } from '@app/database'; import { SharedLinkEntity, SharedLinkType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import _ from 'lodash'; import _ from 'lodash';
import { AlbumResponseDto, mapAlbumExcludeAssetInfo } from '../../album/response-dto/album-response.dto'; import { AlbumResponseDto, mapAlbumExcludeAssetInfo } from '../../album/response-dto/album-response.dto';

View File

@ -1,9 +1,9 @@
import { SharedLinkEntity } from '@app/database/entities/shared-link.entity'; import { SharedLinkEntity } from '@app/infra';
import { CreateSharedLinkDto } from './dto/create-shared-link.dto'; import { CreateSharedLinkDto } from './dto/create-shared-link.dto';
import { ISharedLinkRepository } from './shared-link.repository'; import { ISharedLinkRepository } from './shared-link.repository';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import { BadRequestException, InternalServerErrorException, Logger } from '@nestjs/common'; import { BadRequestException, InternalServerErrorException, Logger } from '@nestjs/common';
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { EditSharedLinkDto } from './dto/edit-shared-link.dto'; import { EditSharedLinkDto } from './dto/edit-shared-link.dto';
export class ShareCore { export class ShareCore {

View File

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ShareService } from './share.service'; import { ShareService } from './share.service';
import { ShareController } from './share.controller'; import { ShareController } from './share.controller';
import { SharedLinkEntity } from '@app/database/entities/shared-link.entity'; import { SharedLinkEntity } from '@app/infra';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { SharedLinkRepository, ISharedLinkRepository } from './shared-link.repository'; import { SharedLinkRepository, ISharedLinkRepository } from './shared-link.repository';

View File

@ -1,4 +1,4 @@
import { SharedLinkEntity } from '@app/database/entities/shared-link.entity'; import { SharedLinkEntity } from '@app/infra';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';

View File

@ -1,4 +1,4 @@
import { SystemConfig } from '@app/database'; import { SystemConfig } from '@app/infra';
import { ValidateNested } from 'class-validator'; import { ValidateNested } from 'class-validator';
import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto'; import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto';
import { SystemConfigOAuthDto } from './system-config-oauth.dto'; import { SystemConfigOAuthDto } from './system-config-oauth.dto';

View File

@ -1,4 +1,4 @@
import { SystemConfigEntity } from '@app/database'; import { SystemConfigEntity } from '@app/infra';
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant'; import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';

View File

@ -1,4 +1,4 @@
import { TagType } from '@app/database'; import { TagType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator';

View File

@ -1,4 +1,4 @@
import { TagEntity, TagType } from '@app/database'; import { TagEntity, TagType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
export class TagResponseDto { export class TagResponseDto {

View File

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TagService } from './tag.service'; import { TagService } from './tag.service';
import { TagController } from './tag.controller'; import { TagController } from './tag.controller';
import { TagEntity } from '@app/database'; import { TagEntity } from '@app/infra';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { TagRepository, ITagRepository } from './tag.repository'; import { TagRepository, ITagRepository } from './tag.repository';

View File

@ -1,4 +1,4 @@
import { TagEntity, TagType } from '@app/database'; import { TagEntity, TagType } from '@app/infra';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm'; import { In, Repository } from 'typeorm';

View File

@ -1,4 +1,4 @@
import { TagEntity, TagType, UserEntity } from '@app/database'; import { TagEntity, TagType, UserEntity } from '@app/infra';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { ITagRepository } from './tag.repository'; import { ITagRepository } from './tag.repository';
import { TagService } from './tag.service'; import { TagService } from './tag.service';

View File

@ -1,4 +1,4 @@
import { TagEntity } from '@app/database'; import { TagEntity } from '@app/infra';
import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common'; import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { CreateTagDto } from './dto/create-tag.dto'; import { CreateTagDto } from './dto/create-tag.dto';

View File

@ -1,23 +0,0 @@
import { UserEntity } from '@app/database';
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { TypeOrmModule } from '@nestjs/typeorm';
import { jwtConfig } from '../../config/jwt.config';
import { ImmichJwtModule } from '../../modules/immich-jwt/immich-jwt.module';
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
import { UserRepository, IUserRepository } from './user-repository';
import { UserController } from './user.controller';
import { UserService } from './user.service';
const USER_REPOSITORY_PROVIDER = {
provide: IUserRepository,
useClass: UserRepository,
};
@Module({
imports: [TypeOrmModule.forFeature([UserEntity]), ImmichJwtModule, JwtModule.register(jwtConfig)],
controllers: [UserController],
providers: [UserService, ImmichJwtService, USER_REPOSITORY_PROVIDER],
exports: [USER_REPOSITORY_PROVIDER],
})
export class UserModule {}

View File

@ -1,6 +1,5 @@
import { immichAppConfig, immichBullAsyncConfig } from '@app/common/config'; import { immichAppConfig, immichBullAsyncConfig } from '@app/common/config';
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { UserModule } from './api-v1/user/user.module';
import { AssetModule } from './api-v1/asset/asset.module'; import { AssetModule } from './api-v1/asset/asset.module';
import { AuthModule } from './api-v1/auth/auth.module'; import { AuthModule } from './api-v1/auth/auth.module';
import { APIKeyModule } from './api-v1/api-key/api-key.module'; import { APIKeyModule } from './api-v1/api-key/api-key.module';
@ -15,20 +14,23 @@ import { AlbumModule } from './api-v1/album/album.module';
import { AppController } from './app.controller'; import { AppController } from './app.controller';
import { ScheduleModule } from '@nestjs/schedule'; import { ScheduleModule } from '@nestjs/schedule';
import { ScheduleTasksModule } from './modules/schedule-tasks/schedule-tasks.module'; import { ScheduleTasksModule } from './modules/schedule-tasks/schedule-tasks.module';
import { DatabaseModule } from '@app/database';
import { JobModule } from './api-v1/job/job.module'; import { JobModule } from './api-v1/job/job.module';
import { SystemConfigModule } from './api-v1/system-config/system-config.module'; import { SystemConfigModule } from './api-v1/system-config/system-config.module';
import { OAuthModule } from './api-v1/oauth/oauth.module'; import { OAuthModule } from './api-v1/oauth/oauth.module';
import { TagModule } from './api-v1/tag/tag.module'; import { TagModule } from './api-v1/tag/tag.module';
import { ImmichConfigModule } from '@app/immich-config'; import { ImmichConfigModule } from '@app/immich-config';
import { ShareModule } from './api-v1/share/share.module'; import { ShareModule } from './api-v1/share/share.module';
import { DomainModule } from '@app/domain';
import { InfraModule } from '@app/infra';
import { UserController } from './controllers';
@Module({ @Module({
imports: [ imports: [
ConfigModule.forRoot(immichAppConfig), ConfigModule.forRoot(immichAppConfig),
DatabaseModule, DomainModule.register({
UserModule, imports: [InfraModule],
}),
APIKeyModule, APIKeyModule,
@ -64,7 +66,11 @@ import { ShareModule } from './api-v1/share/share.module';
ShareModule, ShareModule,
], ],
controllers: [AppController], controllers: [
//
AppController,
UserController,
],
providers: [], providers: [],
}) })
export class AppModule implements NestModule { export class AppModule implements NestModule {

View File

@ -51,7 +51,7 @@ function destination(req: Request, file: Express.Multer.File, cb: any) {
const basePath = APP_UPLOAD_LOCATION; const basePath = APP_UPLOAD_LOCATION;
const sanitizedDeviceId = sanitize(String(req.body['deviceId'])); const sanitizedDeviceId = sanitize(String(req.body['deviceId']));
const originalUploadFolder = join(basePath, req.user.id, 'original', sanitizedDeviceId); const originalUploadFolder = join(basePath, user.id, 'original', sanitizedDeviceId);
if (!existsSync(originalUploadFolder)) { if (!existsSync(originalUploadFolder)) {
mkdirSync(originalUploadFolder, { recursive: true }); mkdirSync(originalUploadFolder, { recursive: true });

View File

@ -6,6 +6,7 @@ import { existsSync, mkdirSync } from 'fs';
import { diskStorage } from 'multer'; import { diskStorage } from 'multer';
import { extname } from 'path'; import { extname } from 'path';
import sanitize from 'sanitize-filename'; import sanitize from 'sanitize-filename';
import { AuthUserDto } from '../decorators/auth-user.decorator';
import { patchFormData } from '../utils/path-form-data.util'; import { patchFormData } from '../utils/path-form-data.util';
export const profileImageUploadOption: MulterOptions = { export const profileImageUploadOption: MulterOptions = {
@ -35,8 +36,10 @@ function destination(req: Request, file: Express.Multer.File, cb: any) {
return cb(new UnauthorizedException()); return cb(new UnauthorizedException());
} }
const user = req.user as AuthUserDto;
const basePath = APP_UPLOAD_LOCATION; const basePath = APP_UPLOAD_LOCATION;
const profileImageLocation = `${basePath}/${req.user.id}/profile`; const profileImageLocation = `${basePath}/${user.id}/profile`;
if (!existsSync(profileImageLocation)) { if (!existsSync(profileImageLocation)) {
mkdirSync(profileImageLocation, { recursive: true }); mkdirSync(profileImageLocation, { recursive: true });

View File

@ -0,0 +1 @@
export * from './user.controller';

View File

@ -15,20 +15,20 @@ import {
StreamableFile, StreamableFile,
Header, Header,
} from '@nestjs/common'; } from '@nestjs/common';
import { UserService } from './user.service'; import { UserService } from '@app/domain';
import { Authenticated } from '../../decorators/authenticated.decorator'; import { Authenticated } from '../decorators/authenticated.decorator';
import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator'; import { AuthUserDto, GetAuthUser } from '../decorators/auth-user.decorator';
import { CreateUserDto } from './dto/create-user.dto'; import { CreateUserDto } from '@app/domain';
import { UpdateUserDto } from './dto/update-user.dto'; import { UpdateUserDto } from '@app/domain';
import { FileInterceptor } from '@nestjs/platform-express'; import { FileInterceptor } from '@nestjs/platform-express';
import { profileImageUploadOption } from '../../config/profile-image-upload.config'; import { profileImageUploadOption } from '../config/profile-image-upload.config';
import { Response as Res } from 'express'; import { Response as Res } from 'express';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger'; import { ApiBearerAuth, ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
import { UserResponseDto } from './response-dto/user-response.dto'; import { UserResponseDto } from '@app/domain';
import { UserCountResponseDto } from './response-dto/user-count-response.dto'; import { UserCountResponseDto } from '@app/domain';
import { CreateProfileImageDto } from './dto/create-profile-image.dto'; import { CreateProfileImageDto } from '@app/domain';
import { CreateProfileImageResponseDto } from './response-dto/create-profile-image-response.dto'; import { CreateProfileImageResponseDto } from '@app/domain';
import { UserCountDto } from './dto/user-count.dto'; import { UserCountDto } from '@app/domain';
@ApiTags('User') @ApiTags('User')
@Controller('user') @Controller('user')

View File

@ -1,14 +1,6 @@
export { AuthUserDto } from '@app/domain';
import { AuthUserDto } from '@app/domain';
import { createParamDecorator, ExecutionContext } from '@nestjs/common'; import { createParamDecorator, ExecutionContext } from '@nestjs/common';
// import { AuthUserDto } from './dto/auth-user.dto';
export class AuthUserDto {
id!: string;
email!: string;
isAdmin!: boolean;
isPublicUser?: boolean;
sharedLinkId?: string;
isAllowUpload?: boolean;
}
export const GetAuthUser = createParamDecorator((data, ctx: ExecutionContext): AuthUserDto => { export const GetAuthUser = createParamDecorator((data, ctx: ExecutionContext): AuthUserDto => {
return ctx.switchToHttp().getRequest<{ user: AuthUserDto }>().user; return ctx.switchToHttp().getRequest<{ user: AuthUserDto }>().user;

View File

@ -1,8 +1,8 @@
import { UserResponseDto } from './api-v1/user/response-dto/user-response.dto'; import { AuthUserDto } from './decorators/auth-user.decorator';
declare global { declare global {
namespace Express { namespace Express {
// eslint-disable-next-line @typescript-eslint/no-empty-interface // eslint-disable-next-line @typescript-eslint/no-empty-interface
interface User extends UserResponseDto {} interface User extends AuthUserDto {}
} }
} }

View File

@ -1,6 +1,6 @@
import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common'; import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { UserResponseDto } from '../api-v1/user/response-dto/user-response.dto'; import { UserResponseDto } from '@app/domain';
interface UserRequest extends Request { interface UserRequest extends Request {
user: UserResponseDto; user: UserResponseDto;

View File

@ -1,7 +1,7 @@
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { AssetEntity, ExifEntity, SmartInfoEntity } from '@app/database'; import { AssetEntity, ExifEntity, SmartInfoEntity } from '@app/infra';
import { BackgroundTaskProcessor } from './background-task.processor'; import { BackgroundTaskProcessor } from './background-task.processor';
import { BackgroundTaskService } from './background-task.service'; import { BackgroundTaskService } from './background-task.service';

View File

@ -1,7 +1,7 @@
import { Process, Processor } from '@nestjs/bull'; import { Process, Processor } from '@nestjs/bull';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { AssetEntity, SmartInfoEntity } from '@app/database'; import { AssetEntity, SmartInfoEntity } from '@app/infra';
import { Job } from 'bull'; import { Job } from 'bull';
import { AssetResponseDto } from '../../api-v1/asset/response-dto/asset-response.dto'; import { AssetResponseDto } from '../../api-v1/asset/response-dto/asset-response.dto';
import { assetUtils } from '@app/common/utils'; import { assetUtils } from '@app/common/utils';

View File

@ -1,4 +1,4 @@
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { BadRequestException, Injectable, InternalServerErrorException, Logger, StreamableFile } from '@nestjs/common'; import { BadRequestException, Injectable, InternalServerErrorException, Logger, StreamableFile } from '@nestjs/common';
import archiver from 'archiver'; import archiver from 'archiver';
import { extname } from 'path'; import { extname } from 'path';

View File

@ -4,7 +4,7 @@ import { JwtModule } from '@nestjs/jwt';
import { jwtConfig } from '../../config/jwt.config'; import { jwtConfig } from '../../config/jwt.config';
import { JwtStrategy } from './strategies/jwt.strategy'; import { JwtStrategy } from './strategies/jwt.strategy';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { APIKeyModule } from '../../api-v1/api-key/api-key.module'; import { APIKeyModule } from '../../api-v1/api-key/api-key.module';
import { APIKeyStrategy } from './strategies/api-key.strategy'; import { APIKeyStrategy } from './strategies/api-key.strategy';
import { ShareModule } from '../../api-v1/share/share.module'; import { ShareModule } from '../../api-v1/share/share.module';

View File

@ -1,7 +1,7 @@
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { Request } from 'express'; import { Request } from 'express';
import { UserEntity } from '../../../../../libs/database/src/entities/user.entity'; import { UserEntity } from '@app/infra';
import { LoginResponseDto } from '../../api-v1/auth/response-dto/login-response.dto'; import { LoginResponseDto } from '../../api-v1/auth/response-dto/login-response.dto';
import { AuthType } from '../../constants/jwt.constant'; import { AuthType } from '../../constants/jwt.constant';
import { ImmichJwtService } from './immich-jwt.service'; import { ImmichJwtService } from './immich-jwt.service';

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { Request } from 'express'; import { Request } from 'express';

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport'; import { PassportStrategy } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport'; import { PassportStrategy } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';

View File

@ -1,7 +1,7 @@
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { AssetEntity, ExifEntity, UserEntity } from '@app/database'; import { AssetEntity, ExifEntity, UserEntity } from '@app/infra';
import { ScheduleTasksService } from './schedule-tasks.service'; import { ScheduleTasksService } from './schedule-tasks.service';
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant'; import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';

View File

@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule'; import { Cron, CronExpression } from '@nestjs/schedule';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Not, Repository } from 'typeorm'; import { IsNull, Not, Repository } from 'typeorm';
import { AssetEntity, AssetType, ExifEntity, UserEntity } from '@app/database'; import { AssetEntity, AssetType, ExifEntity, UserEntity } from '@app/infra';
import { InjectQueue } from '@nestjs/bull'; import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull'; import { Queue } from 'bull';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';

View File

@ -3,13 +3,12 @@ import { INestApplication } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import request from 'supertest'; import request from 'supertest';
import { clearDb, getAuthUser, authCustom } from './test-utils'; import { clearDb, getAuthUser, authCustom } from './test-utils';
import { databaseConfig } from '@app/database'; import { databaseConfig } from '@app/infra';
import { AlbumModule } from '../src/api-v1/album/album.module'; import { AlbumModule } from '../src/api-v1/album/album.module';
import { CreateAlbumDto } from '../src/api-v1/album/dto/create-album.dto'; import { CreateAlbumDto } from '../src/api-v1/album/dto/create-album.dto';
import { ImmichJwtModule } from '../src/modules/immich-jwt/immich-jwt.module'; import { ImmichJwtModule } from '../src/modules/immich-jwt/immich-jwt.module';
import { AuthUserDto } from '../src/decorators/auth-user.decorator'; import { AuthUserDto } from '../src/decorators/auth-user.decorator';
import { UserService } from '../src/api-v1/user/user.service'; import { UserService } from '@app/domain';
import { UserModule } from '../src/api-v1/user/user.module';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
function _createAlbum(app: INestApplication, data: CreateAlbumDto) { function _createAlbum(app: INestApplication, data: CreateAlbumDto) {
@ -52,7 +51,7 @@ describe('Album', () => {
beforeAll(async () => { beforeAll(async () => {
const builder = Test.createTestingModule({ const builder = Test.createTestingModule({
imports: [AlbumModule, UserModule, TypeOrmModule.forRoot(databaseConfig)], imports: [AlbumModule, TypeOrmModule.forRoot(databaseConfig)],
}); });
authUser = getAuthUser(); // set default auth user authUser = getAuthUser(); // set default auth user
const moduleFixture: TestingModule = await authCustom(builder, () => authUser).compile(); const moduleFixture: TestingModule = await authCustom(builder, () => authUser).compile();

View File

@ -7,15 +7,11 @@
"^.+\\.(t|j)s$": "ts-jest" "^.+\\.(t|j)s$": "ts-jest"
}, },
"moduleNameMapper": { "moduleNameMapper": {
"^@app/database(|/.*)$": "<rootDir>../../../libs/database/src/$1", "^@app/common": "<rootDir>../../../libs/common/src",
"@app/database/config": "<rootDir>../../../libs/database/src/config",
"@app/database/config/(.*)": "<rootDir>../../../libs/database/src/config/$1",
"@app/database/entities/(.*)": "<rootDir>../../../libs/database/src/entities/$1",
"@app/common": "<rootDir>../../../libs/common/src",
"@app/common/(.*)": "<rootDir>../../../libs/common/src/$1",
"^@app/job(|/.*)$": "<rootDir>../../../libs/job/src/$1", "^@app/job(|/.*)$": "<rootDir>../../../libs/job/src/$1",
"@app/job": "<rootDir>../../../libs/job/src",
"^@app/immich-config(|/.*)$": "<rootDir>../../../libs/immich-config/src/$1", "^@app/immich-config(|/.*)$": "<rootDir>../../../libs/immich-config/src/$1",
"^@app/storage(|/.*)$": "<rootDir>../../../libs/storage/src/$1" "^@app/storage(|/.*)$": "<rootDir>../../../libs/storage/src/$1",
"^@app/infra(|/.*)$": "<rootDir>../../../libs/infra/src/$1",
"^@app/domain(|/.*)$": "<rootDir>../../../libs/domain/src/$1"
} }
} }

View File

@ -1,7 +1,6 @@
import { CanActivate, ExecutionContext } from '@nestjs/common'; import { CanActivate, ExecutionContext } from '@nestjs/common';
import { TestingModuleBuilder } from '@nestjs/testing'; import { TestingModuleBuilder } from '@nestjs/testing';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import { IUserRepository } from '../src/api-v1/user/user-repository';
import { AuthUserDto } from '../src/decorators/auth-user.decorator'; import { AuthUserDto } from '../src/decorators/auth-user.decorator';
import { AuthGuard } from '../src/modules/immich-jwt/guards/auth.guard'; import { AuthGuard } from '../src/modules/immich-jwt/guards/auth.guard';
@ -15,20 +14,6 @@ export async function clearDb(db: DataSource) {
} }
} }
export function newUserRepositoryMock(): jest.Mocked<IUserRepository> {
return {
get: jest.fn(),
getAdmin: jest.fn(),
getByEmail: jest.fn(),
getByOAuthId: jest.fn(),
getList: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
restore: jest.fn(),
};
}
export function getAuthUser(): AuthUserDto { export function getAuthUser(): AuthUserDto {
return { return {
id: '3108ac14-8afb-4b7e-87fd-39ebb6b79750', id: '3108ac14-8afb-4b7e-87fd-39ebb6b79750',

View File

@ -3,12 +3,9 @@ import { INestApplication } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import request from 'supertest'; import request from 'supertest';
import { clearDb, authCustom } from './test-utils'; import { clearDb, authCustom } from './test-utils';
import { databaseConfig } from '@app/database/config/database.config'; import { databaseConfig } from '@app/infra';
import { UserModule } from '../src/api-v1/user/user.module';
import { ImmichJwtModule } from '../src/modules/immich-jwt/immich-jwt.module'; import { ImmichJwtModule } from '../src/modules/immich-jwt/immich-jwt.module';
import { UserService } from '../src/api-v1/user/user.service'; import { CreateAdminDto, CreateUserDto, UserResponseDto, UserService } from '@app/domain';
import { CreateAdminDto, CreateUserDto } from '../src/api-v1/user/dto/create-user.dto';
import { UserResponseDto } from '../src/api-v1/user/response-dto/user-response.dto';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
function _createUser(userService: UserService, data: CreateUserDto | CreateAdminDto) { function _createUser(userService: UserService, data: CreateUserDto | CreateAdminDto) {
@ -27,7 +24,7 @@ describe('User', () => {
describe('without auth', () => { describe('without auth', () => {
beforeAll(async () => { beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({ const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [UserModule, ImmichJwtModule, TypeOrmModule.forRoot(databaseConfig)], imports: [ImmichJwtModule, TypeOrmModule.forRoot(databaseConfig)],
}).compile(); }).compile();
app = moduleFixture.createNestApplication(); app = moduleFixture.createNestApplication();
@ -51,7 +48,7 @@ describe('User', () => {
beforeAll(async () => { beforeAll(async () => {
const builder = Test.createTestingModule({ const builder = Test.createTestingModule({
imports: [UserModule, TypeOrmModule.forRoot(databaseConfig)], imports: [TypeOrmModule.forRoot(databaseConfig)],
}); });
const moduleFixture: TestingModule = await authCustom(builder, () => authUser).compile(); const moduleFixture: TestingModule = await authCustom(builder, () => authUser).compile();

View File

@ -1,5 +1,5 @@
import { immichAppConfig, immichBullAsyncConfig } from '@app/common/config'; import { immichAppConfig, immichBullAsyncConfig } from '@app/common/config';
import { DatabaseModule, AssetEntity, ExifEntity, SmartInfoEntity, UserEntity, APIKeyEntity } from '@app/database'; import { AssetEntity, ExifEntity, SmartInfoEntity, UserEntity, APIKeyEntity, InfraModule } from '@app/infra';
import { StorageModule } from '@app/storage'; import { StorageModule } from '@app/storage';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
@ -17,11 +17,14 @@ import { ThumbnailGeneratorProcessor } from './processors/thumbnail.processor';
import { UserDeletionProcessor } from './processors/user-deletion.processor'; import { UserDeletionProcessor } from './processors/user-deletion.processor';
import { VideoTranscodeProcessor } from './processors/video-transcode.processor'; import { VideoTranscodeProcessor } from './processors/video-transcode.processor';
import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant'; import { immichSharedQueues } from '@app/job/constants/bull-queue-registration.constant';
import { DomainModule } from '@app/domain';
@Module({ @Module({
imports: [ imports: [
ConfigModule.forRoot(immichAppConfig), ConfigModule.forRoot(immichAppConfig),
DatabaseModule, DomainModule.register({
imports: [InfraModule],
}),
ImmichConfigModule, ImmichConfigModule,
TypeOrmModule.forFeature([UserEntity, ExifEntity, AssetEntity, SmartInfoEntity, APIKeyEntity]), TypeOrmModule.forFeature([UserEntity, ExifEntity, AssetEntity, SmartInfoEntity, APIKeyEntity]),
StorageModule, StorageModule,

View File

@ -1,4 +1,4 @@
import { AssetType } from '@app/database'; import { AssetType } from '@app/infra';
import { import {
IAssetUploadedJob, IAssetUploadedJob,
IMetadataExtractionJob, IMetadataExtractionJob,

View File

@ -1,4 +1,4 @@
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { QueueNameEnum } from '@app/job'; import { QueueNameEnum } from '@app/job';
import { Process, Processor } from '@nestjs/bull'; import { Process, Processor } from '@nestjs/bull';
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';

View File

@ -1,5 +1,5 @@
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { SmartInfoEntity } from '@app/database'; import { SmartInfoEntity } from '@app/infra';
import { MachineLearningJobNameEnum, QueueNameEnum } from '@app/job'; import { MachineLearningJobNameEnum, QueueNameEnum } from '@app/job';
import { IMachineLearningJob } from '@app/job/interfaces/machine-learning.interface'; import { IMachineLearningJob } from '@app/job/interfaces/machine-learning.interface';
import { Process, Processor } from '@nestjs/bull'; import { Process, Processor } from '@nestjs/bull';

View File

@ -1,5 +1,5 @@
import { ImmichLogLevel } from '@app/common/constants/log-level.constant'; import { ImmichLogLevel } from '@app/common/constants/log-level.constant';
import { AssetEntity, ExifEntity } from '@app/database'; import { AssetEntity, ExifEntity } from '@app/infra';
import { import {
IExifExtractionProcessor, IExifExtractionProcessor,
IVideoLengthExtractionProcessor, IVideoLengthExtractionProcessor,

View File

@ -1,5 +1,5 @@
import { APP_UPLOAD_LOCATION } from '@app/common'; import { APP_UPLOAD_LOCATION } from '@app/common';
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { ImmichConfigService } from '@app/immich-config'; import { ImmichConfigService } from '@app/immich-config';
import { QueueNameEnum, templateMigrationProcessorName, updateTemplateProcessorName } from '@app/job'; import { QueueNameEnum, templateMigrationProcessorName, updateTemplateProcessorName } from '@app/job';
import { StorageService } from '@app/storage'; import { StorageService } from '@app/storage';

View File

@ -1,5 +1,5 @@
import { APP_UPLOAD_LOCATION } from '@app/common'; import { APP_UPLOAD_LOCATION } from '@app/common';
import { AssetEntity, AssetType } from '@app/database'; import { AssetEntity, AssetType } from '@app/infra';
import { import {
WebpGeneratorProcessor, WebpGeneratorProcessor,
generateJPEGThumbnailProcessorName, generateJPEGThumbnailProcessorName,

View File

@ -1,5 +1,5 @@
import { APP_UPLOAD_LOCATION, userUtils } from '@app/common'; import { APP_UPLOAD_LOCATION, userUtils } from '@app/common';
import { APIKeyEntity, AssetEntity, UserEntity } from '@app/database'; import { APIKeyEntity, AssetEntity, UserEntity } from '@app/infra';
import { QueueNameEnum, userDeletionProcessorName } from '@app/job'; import { QueueNameEnum, userDeletionProcessorName } from '@app/job';
import { IUserDeletionJob } from '@app/job/interfaces/user-deletion.interface'; import { IUserDeletionJob } from '@app/job/interfaces/user-deletion.interface';
import { Process, Processor } from '@nestjs/bull'; import { Process, Processor } from '@nestjs/bull';

View File

@ -1,5 +1,5 @@
import { APP_UPLOAD_LOCATION } from '@app/common/constants'; import { APP_UPLOAD_LOCATION } from '@app/common/constants';
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { QueueNameEnum } from '@app/job'; import { QueueNameEnum } from '@app/job';
import { mp4ConversionProcessorName } from '@app/job/constants/job-name.constant'; import { mp4ConversionProcessorName } from '@app/job/constants/job-name.constant';
import { IMp4ConversionProcessor } from '@app/job/interfaces/video-transcode.interface'; import { IMp4ConversionProcessor } from '@app/job/interfaces/video-transcode.interface';

View File

@ -473,147 +473,6 @@
] ]
} }
}, },
"/share": {
"get": {
"operationId": "getAllSharedLinks",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
}
},
"tags": [
"share"
]
}
},
"/share/me": {
"get": {
"operationId": "getMySharedLink",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
},
"tags": [
"share"
]
}
},
"/share/{id}": {
"get": {
"operationId": "getSharedLinkById",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
},
"tags": [
"share"
]
},
"delete": {
"operationId": "removeSharedLink",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
},
"tags": [
"share"
]
},
"patch": {
"operationId": "editSharedLink",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EditSharedLinkDto"
}
}
}
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
},
"tags": [
"share"
]
}
},
"/asset/upload": { "/asset/upload": {
"post": { "post": {
"operationId": "uploadFile", "operationId": "uploadFile",
@ -1370,6 +1229,147 @@
] ]
} }
}, },
"/share": {
"get": {
"operationId": "getAllSharedLinks",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
}
},
"tags": [
"share"
]
}
},
"/share/me": {
"get": {
"operationId": "getMySharedLink",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
},
"tags": [
"share"
]
}
},
"/share/{id}": {
"get": {
"operationId": "getSharedLinkById",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
},
"tags": [
"share"
]
},
"delete": {
"operationId": "removeSharedLink",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
},
"tags": [
"share"
]
},
"patch": {
"operationId": "editSharedLink",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EditSharedLinkDto"
}
}
}
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharedLinkResponseDto"
}
}
}
}
},
"tags": [
"share"
]
}
},
"/album/count-by-user-id": { "/album/count-by-user-id": {
"get": { "get": {
"operationId": "getAlbumCountByUserId", "operationId": "getAlbumCountByUserId",
@ -2879,11 +2879,114 @@
"name" "name"
] ]
}, },
"SharedLinkType": { "AssetFileUploadDto": {
"type": "object",
"properties": {
"assetData": {
"type": "string",
"format": "binary"
}
},
"required": [
"assetData"
]
},
"AssetFileUploadResponseDto": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
},
"required": [
"id"
]
},
"DownloadFilesDto": {
"type": "object",
"properties": {
"assetIds": {
"title": "Array of asset ids to be downloaded",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"assetIds"
]
},
"ThumbnailFormat": {
"type": "string", "type": "string",
"enum": [ "enum": [
"ALBUM", "JPEG",
"INDIVIDUAL" "WEBP"
]
},
"CuratedObjectsResponseDto": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string"
},
"resizePath": {
"type": "string"
},
"deviceAssetId": {
"type": "string"
},
"deviceId": {
"type": "string"
}
},
"required": [
"id",
"object",
"resizePath",
"deviceAssetId",
"deviceId"
]
},
"CuratedLocationsResponseDto": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"city": {
"type": "string"
},
"resizePath": {
"type": "string"
},
"deviceAssetId": {
"type": "string"
},
"deviceId": {
"type": "string"
}
},
"required": [
"id",
"city",
"resizePath",
"deviceAssetId",
"deviceId"
]
},
"SearchAssetDto": {
"type": "object",
"properties": {
"searchTerm": {
"type": "string"
}
},
"required": [
"searchTerm"
] ]
}, },
"AssetTypeEnum": { "AssetTypeEnum": {
@ -3144,232 +3247,6 @@
"tags" "tags"
] ]
}, },
"AlbumResponseDto": {
"type": "object",
"properties": {
"assetCount": {
"type": "integer"
},
"id": {
"type": "string"
},
"ownerId": {
"type": "string"
},
"albumName": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"albumThumbnailAssetId": {
"type": "string",
"nullable": true
},
"shared": {
"type": "boolean"
},
"sharedUsers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserResponseDto"
}
},
"assets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AssetResponseDto"
}
}
},
"required": [
"assetCount",
"id",
"ownerId",
"albumName",
"createdAt",
"albumThumbnailAssetId",
"shared",
"sharedUsers",
"assets"
]
},
"SharedLinkResponseDto": {
"type": "object",
"properties": {
"type": {
"$ref": "#/components/schemas/SharedLinkType"
},
"id": {
"type": "string"
},
"description": {
"type": "string"
},
"userId": {
"type": "string"
},
"key": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"expiresAt": {
"type": "string",
"nullable": true
},
"assets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AssetResponseDto"
}
},
"album": {
"$ref": "#/components/schemas/AlbumResponseDto"
},
"allowUpload": {
"type": "boolean"
}
},
"required": [
"type",
"id",
"userId",
"key",
"createdAt",
"expiresAt",
"assets",
"allowUpload"
]
},
"EditSharedLinkDto": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"expiredAt": {
"type": "string"
},
"allowUpload": {
"type": "boolean"
},
"isEditExpireTime": {
"type": "boolean"
}
}
},
"AssetFileUploadDto": {
"type": "object",
"properties": {
"assetData": {
"type": "string",
"format": "binary"
}
},
"required": [
"assetData"
]
},
"AssetFileUploadResponseDto": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
},
"required": [
"id"
]
},
"DownloadFilesDto": {
"type": "object",
"properties": {
"assetIds": {
"title": "Array of asset ids to be downloaded",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"assetIds"
]
},
"ThumbnailFormat": {
"type": "string",
"enum": [
"JPEG",
"WEBP"
]
},
"CuratedObjectsResponseDto": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string"
},
"resizePath": {
"type": "string"
},
"deviceAssetId": {
"type": "string"
},
"deviceId": {
"type": "string"
}
},
"required": [
"id",
"object",
"resizePath",
"deviceAssetId",
"deviceId"
]
},
"CuratedLocationsResponseDto": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"city": {
"type": "string"
},
"resizePath": {
"type": "string"
},
"deviceAssetId": {
"type": "string"
},
"deviceId": {
"type": "string"
}
},
"required": [
"id",
"city",
"resizePath",
"deviceAssetId",
"deviceId"
]
},
"SearchAssetDto": {
"type": "object",
"properties": {
"searchTerm": {
"type": "string"
}
},
"required": [
"searchTerm"
]
},
"TimeGroupEnum": { "TimeGroupEnum": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -3596,6 +3473,129 @@
"existingIds" "existingIds"
] ]
}, },
"SharedLinkType": {
"type": "string",
"enum": [
"ALBUM",
"INDIVIDUAL"
]
},
"AlbumResponseDto": {
"type": "object",
"properties": {
"assetCount": {
"type": "integer"
},
"id": {
"type": "string"
},
"ownerId": {
"type": "string"
},
"albumName": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"albumThumbnailAssetId": {
"type": "string",
"nullable": true
},
"shared": {
"type": "boolean"
},
"sharedUsers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserResponseDto"
}
},
"assets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AssetResponseDto"
}
}
},
"required": [
"assetCount",
"id",
"ownerId",
"albumName",
"createdAt",
"albumThumbnailAssetId",
"shared",
"sharedUsers",
"assets"
]
},
"SharedLinkResponseDto": {
"type": "object",
"properties": {
"type": {
"$ref": "#/components/schemas/SharedLinkType"
},
"id": {
"type": "string"
},
"description": {
"type": "string"
},
"userId": {
"type": "string"
},
"key": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"expiresAt": {
"type": "string",
"nullable": true
},
"assets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AssetResponseDto"
}
},
"album": {
"$ref": "#/components/schemas/AlbumResponseDto"
},
"allowUpload": {
"type": "boolean"
}
},
"required": [
"type",
"id",
"userId",
"key",
"createdAt",
"expiresAt",
"assets",
"allowUpload"
]
},
"EditSharedLinkDto": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"expiredAt": {
"type": "string"
},
"allowUpload": {
"type": "boolean"
},
"isEditExpireTime": {
"type": "boolean"
}
}
},
"AlbumCountResponseDto": { "AlbumCountResponseDto": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -1,4 +1,4 @@
import { AssetEntity } from '@app/database'; import { AssetEntity } from '@app/infra';
import { AssetResponseDto } from 'apps/immich/src/api-v1/asset/response-dto/asset-response.dto'; import { AssetResponseDto } from 'apps/immich/src/api-v1/asset/response-dto/asset-response.dto';
import fs from 'fs'; import fs from 'fs';

View File

@ -1,6 +1,6 @@
// create unit test for user utils // create unit test for user utils
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
import { userUtils } from './user-utils'; import { userUtils } from './user-utils';
describe('User Utilities', () => { describe('User Utilities', () => {

View File

@ -1,4 +1,4 @@
import { UserEntity } from '@app/database'; import { UserEntity } from '@app/infra';
function createUserUtils() { function createUserUtils() {
const isReadyForDeletion = (user: UserEntity): boolean => { const isReadyForDeletion = (user: UserEntity): boolean => {

View File

@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { databaseConfig } from './config/database.config';
@Module({
imports: [TypeOrmModule.forRoot(databaseConfig)],
providers: [],
exports: [TypeOrmModule],
})
export class DatabaseModule {}

View File

@ -0,0 +1,8 @@
export class AuthUserDto {
id!: string;
email!: string;
isAdmin!: boolean;
isPublicUser?: boolean;
sharedLinkId?: string;
isAllowUpload?: boolean;
}

View File

@ -0,0 +1 @@
export * from './auth-user.dto';

View File

@ -0,0 +1 @@
export * from './dto';

View File

@ -0,0 +1,20 @@
import { DynamicModule, Global, Module, ModuleMetadata, Provider } from '@nestjs/common';
import { UserService } from './user';
const providers: Provider[] = [
//
UserService,
];
@Global()
@Module({})
export class DomainModule {
static register(options: Pick<ModuleMetadata, 'imports'>): DynamicModule {
return {
module: DomainModule,
imports: options.imports,
providers: [...providers],
exports: [...providers],
};
}
}

View File

@ -0,0 +1,3 @@
export * from './auth';
export * from './domain.module';
export * from './user';

View File

@ -0,0 +1,4 @@
export * from './create-profile-image.dto';
export * from './create-user.dto';
export * from './update-user.dto';
export * from './user-count.dto';

Some files were not shown because too many files have changed in this diff Show More