mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	feat(server): reset admin password using cli command in the server container (#928)
This commit is contained in:
		| @@ -26,9 +26,10 @@ RUN mkdir -p /usr/src/app/dist \ | ||||
|  | ||||
| COPY --from=builder /usr/src/app/node_modules ./node_modules | ||||
| COPY --from=builder /usr/src/app/dist ./dist | ||||
| COPY --from=builder /usr/src/app/bin ./bin | ||||
|  | ||||
| RUN npm prune --production | ||||
|  | ||||
| VOLUME /usr/src/app/upload | ||||
|  | ||||
| EXPOSE 3001 | ||||
| EXPOSE 3001 | ||||
|   | ||||
							
								
								
									
										11
									
								
								server/apps/cli/src/app.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								server/apps/cli/src/app.module.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| import { DatabaseModule } from '@app/database'; | ||||
| import { UserEntity } from '@app/database/entities/user.entity'; | ||||
| import { Module } from '@nestjs/common'; | ||||
| import { TypeOrmModule } from '@nestjs/typeorm'; | ||||
| import { PromptPasswordQuestions, ResetAdminPasswordCommand } from './commands/reset-admin-password.command'; | ||||
|  | ||||
| @Module({ | ||||
|   imports: [DatabaseModule, TypeOrmModule.forFeature([UserEntity])], | ||||
|   providers: [ResetAdminPasswordCommand, PromptPasswordQuestions], | ||||
| }) | ||||
| export class AppModule {} | ||||
							
								
								
									
										52
									
								
								server/apps/cli/src/commands/reset-admin-password.command.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								server/apps/cli/src/commands/reset-admin-password.command.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| import { UserEntity } from '@app/database/entities/user.entity'; | ||||
| import { InjectRepository } from '@nestjs/typeorm'; | ||||
| import bcrypt from 'bcrypt'; | ||||
| import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander'; | ||||
| import { randomBytes } from 'node:crypto'; | ||||
| import { Repository } from 'typeorm'; | ||||
|  | ||||
| @Command({ | ||||
|   name: 'reset-admin-password', | ||||
|   description: 'Reset the admin password', | ||||
| }) | ||||
| export class ResetAdminPasswordCommand extends CommandRunner { | ||||
|   constructor( | ||||
|     private readonly inquirer: InquirerService, | ||||
|     @InjectRepository(UserEntity) private userRepository: Repository<UserEntity>, | ||||
|   ) { | ||||
|     super(); | ||||
|   } | ||||
|  | ||||
|   async run(): Promise<void> { | ||||
|     let { password } = await this.inquirer.ask<{ password: string }>('prompt-password', undefined); | ||||
|     password = password || randomBytes(24).toString('base64').replace(/\W/g, ''); | ||||
|  | ||||
|     const salt = await bcrypt.genSalt(); | ||||
|     const hashedPassword = await bcrypt.hash(password, salt); | ||||
|  | ||||
|     const user = await this.userRepository.findOne({ where: { isAdmin: true } }); | ||||
|     if (!user) { | ||||
|       console.log('Unable to reset password: no admin user.'); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     user.salt = salt; | ||||
|     user.password = hashedPassword; | ||||
|     user.shouldChangePassword = true; | ||||
|  | ||||
|     await this.userRepository.save(user); | ||||
|  | ||||
|     console.log(`New password:\n${password}`); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @QuestionSet({ name: 'prompt-password' }) | ||||
| export class PromptPasswordQuestions { | ||||
|   @Question({ | ||||
|     message: 'Please choose a new password (optional)', | ||||
|     name: 'password', | ||||
|   }) | ||||
|   parsePassword(val: string) { | ||||
|     return val; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										7
									
								
								server/apps/cli/src/immich.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										7
									
								
								server/apps/cli/src/immich.ts
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import { CommandFactory } from 'nest-commander'; | ||||
| import { AppModule } from './app.module'; | ||||
|  | ||||
| async function bootstrap() { | ||||
|   await CommandFactory.run(AppModule, ['warn', 'error']); | ||||
| } | ||||
| bootstrap(); | ||||
							
								
								
									
										9
									
								
								server/apps/cli/tsconfig.app.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								server/apps/cli/tsconfig.app.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| { | ||||
|   "extends": "../../tsconfig.json", | ||||
|   "compilerOptions": { | ||||
|     "declaration": false, | ||||
|     "outDir": "../../dist/apps/cli" | ||||
|   }, | ||||
|   "include": ["src/**/*", "../../libs/**/*"], | ||||
|   "exclude": ["node_modules", "dist", "test", "**/*spec.ts"] | ||||
| } | ||||
							
								
								
									
										1
									
								
								server/bin/cli.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								server/bin/cli.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| node ./dist/apps/cli/apps/cli/src/immich "$@" | ||||
| @@ -6,13 +6,15 @@ | ||||
|   "compilerOptions": { | ||||
|     "webpack": false, | ||||
|     "tsConfigPath": "apps/immich/tsconfig.app.json", | ||||
|     "plugins": [  { | ||||
|       "name": "@nestjs/swagger", | ||||
|       "options": { | ||||
|         "classValidatorShim": false, | ||||
|         "introspectComments": true | ||||
|     "plugins": [ | ||||
|       { | ||||
|         "name": "@nestjs/swagger", | ||||
|         "options": { | ||||
|           "classValidatorShim": false, | ||||
|           "introspectComments": true | ||||
|         } | ||||
|       } | ||||
|     }] | ||||
|     ] | ||||
|   }, | ||||
|   "projects": { | ||||
|     "immich": { | ||||
| @@ -33,6 +35,15 @@ | ||||
|         "tsConfigPath": "apps/microservices/tsconfig.app.json" | ||||
|       } | ||||
|     }, | ||||
|     "cli": { | ||||
|       "type": "application", | ||||
|       "root": "apps/cli", | ||||
|       "entryFile": "immich", | ||||
|       "sourceRoot": "apps/cli/src", | ||||
|       "compilerOptions": { | ||||
|         "tsConfigPath": "apps/cli/tsconfig.app.json" | ||||
|       } | ||||
|     }, | ||||
|     "common": { | ||||
|       "type": "library", | ||||
|       "root": "libs/common", | ||||
|   | ||||
							
								
								
									
										465
									
								
								server/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										465
									
								
								server/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -5,9 +5,12 @@ | ||||
|   "author": "", | ||||
|   "private": true, | ||||
|   "license": "UNLICENSED", | ||||
|   "bin": { | ||||
|     "immich": "./bin/cli.sh" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "prebuild": "rimraf dist", | ||||
|     "build": "nest build immich && nest build microservices", | ||||
|     "build": "nest build immich && nest build microservices && nest build cli", | ||||
|     "format": "prettier --write \"apps/**/*.ts\" \"libs/**/*.ts\"", | ||||
|     "start": "nest start", | ||||
|     "start:dev": "nest start --watch", | ||||
| @@ -59,6 +62,7 @@ | ||||
|     "local-reverse-geocoder": "^0.12.5", | ||||
|     "lodash": "^4.17.21", | ||||
|     "luxon": "^3.0.3", | ||||
|     "nest-commander": "^3.3.0", | ||||
|     "passport": "^0.6.0", | ||||
|     "passport-jwt": "^4.0.0", | ||||
|     "pg": "^8.7.1", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user