summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/CreateSystemUserService.ts
blob: 1e753f65cc027b92a96a0a2ad14e0175ada8aca8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { Inject, Injectable } from '@nestjs/common';
import bcrypt from 'bcryptjs';
import { v4 as uuid } from 'uuid';
import { IsNull, DataSource } from 'typeorm';
import { genRsaKeyPair } from '@/misc/gen-key-pair.js';
import { User } from '@/models/entities/User.js';
import { UserProfile } from '@/models/entities/UserProfile.js';
import { IdService } from '@/core/IdService.js';
import { UserKeypair } from '@/models/entities/UserKeypair.js';
import { UsedUsername } from '@/models/entities/UsedUsername.js';
import { DI } from '@/di-symbols.js';
import generateNativeUserToken from '@/misc/generate-native-user-token.js';
import { bindThis } from '@/decorators.js';

@Injectable()
export class CreateSystemUserService {
	constructor(
		@Inject(DI.db)
		private db: DataSource,

		private idService: IdService,
	) {
	}

	@bindThis
	public async createSystemUser(username: string): Promise<User> {
		const password = uuid();
	
		// Generate hash of password
		const salt = await bcrypt.genSalt(8);
		const hash = await bcrypt.hash(password, salt);
	
		// Generate secret
		const secret = generateNativeUserToken();
	
		const keyPair = await genRsaKeyPair(4096);
	
		let account!: User;
	
		// Start transaction
		await this.db.transaction(async transactionalEntityManager => {
			const exist = await transactionalEntityManager.findOneBy(User, {
				usernameLower: username.toLowerCase(),
				host: IsNull(),
			});
	
			if (exist) throw new Error('the user is already exists');
	
			account = await transactionalEntityManager.insert(User, {
				id: this.idService.genId(),
				createdAt: new Date(),
				username: username,
				usernameLower: username.toLowerCase(),
				host: null,
				token: secret,
				isAdmin: false,
				isLocked: true,
				isExplorable: false,
				isBot: true,
			}).then(x => transactionalEntityManager.findOneByOrFail(User, x.identifiers[0]));
	
			await transactionalEntityManager.insert(UserKeypair, {
				publicKey: keyPair.publicKey,
				privateKey: keyPair.privateKey,
				userId: account.id,
			});
	
			await transactionalEntityManager.insert(UserProfile, {
				userId: account.id,
				autoAcceptFollowed: false,
				password: hash,
			});
	
			await transactionalEntityManager.insert(UsedUsername, {
				createdAt: new Date(),
				username: username.toLowerCase(),
			});
		});
	
		return account;
	}
}