1
0
mirror of https://github.com/immich-app/immich.git synced 2024-11-24 08:52:28 +02:00

feat(server): reset admin password using cli command in the server container (#928)

This commit is contained in:
Jason Rasmussen 2022-11-05 12:28:40 -04:00 committed by GitHub
parent dd8a4c0c56
commit 02bc84062e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 300 additions and 277 deletions

View File

@ -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/node_modules ./node_modules
COPY --from=builder /usr/src/app/dist ./dist COPY --from=builder /usr/src/app/dist ./dist
COPY --from=builder /usr/src/app/bin ./bin
RUN npm prune --production RUN npm prune --production
VOLUME /usr/src/app/upload VOLUME /usr/src/app/upload
EXPOSE 3001 EXPOSE 3001

View 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 {}

View 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
View 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();

View 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
View File

@ -0,0 +1 @@
node ./dist/apps/cli/apps/cli/src/immich "$@"

View File

@ -6,13 +6,15 @@
"compilerOptions": { "compilerOptions": {
"webpack": false, "webpack": false,
"tsConfigPath": "apps/immich/tsconfig.app.json", "tsConfigPath": "apps/immich/tsconfig.app.json",
"plugins": [ { "plugins": [
"name": "@nestjs/swagger", {
"options": { "name": "@nestjs/swagger",
"classValidatorShim": false, "options": {
"introspectComments": true "classValidatorShim": false,
"introspectComments": true
}
} }
}] ]
}, },
"projects": { "projects": {
"immich": { "immich": {
@ -33,6 +35,15 @@
"tsConfigPath": "apps/microservices/tsconfig.app.json" "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": { "common": {
"type": "library", "type": "library",
"root": "libs/common", "root": "libs/common",

465
server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,12 @@
"author": "", "author": "",
"private": true, "private": true,
"license": "UNLICENSED", "license": "UNLICENSED",
"bin": {
"immich": "./bin/cli.sh"
},
"scripts": { "scripts": {
"prebuild": "rimraf dist", "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\"", "format": "prettier --write \"apps/**/*.ts\" \"libs/**/*.ts\"",
"start": "nest start", "start": "nest start",
"start:dev": "nest start --watch", "start:dev": "nest start --watch",
@ -59,6 +62,7 @@
"local-reverse-geocoder": "^0.12.5", "local-reverse-geocoder": "^0.12.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"luxon": "^3.0.3", "luxon": "^3.0.3",
"nest-commander": "^3.3.0",
"passport": "^0.6.0", "passport": "^0.6.0",
"passport-jwt": "^4.0.0", "passport-jwt": "^4.0.0",
"pg": "^8.7.1", "pg": "^8.7.1",