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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiRegistryItem, RegistryItemsRepository } from '@/models/_.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import type { MiUser } from '@/models/User.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { bindThis } from '@/decorators.js';
@Injectable()
export class RegistryApiService {
constructor(
@Inject(DI.registryItemsRepository)
private registryItemsRepository: RegistryItemsRepository,
private idService: IdService,
private globalEventService: GlobalEventService,
) {
}
@bindThis
public async set(userId: MiUser['id'], domain: string | null, scope: string[], key: string, value: any) {
// TODO: 作成できるキーの数を制限する
const query = this.registryItemsRepository.createQueryBuilder('item');
if (domain) {
query.where('item.domain = :domain', { domain: domain });
} else {
query.where('item.domain IS NULL');
}
query.andWhere('item.userId = :userId', { userId: userId });
query.andWhere('item.key = :key', { key: key });
query.andWhere('item.scope = :scope', { scope: scope });
const existingItem = await query.getOne();
if (existingItem) {
await this.registryItemsRepository.update(existingItem.id, {
updatedAt: new Date(),
value: value,
});
} else {
await this.registryItemsRepository.insert({
id: this.idService.gen(),
updatedAt: new Date(),
userId: userId,
domain: domain,
scope: scope,
key: key,
value: value,
});
}
if (domain == null) {
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
this.globalEventService.publishMainStream(userId, 'registryUpdated', {
scope: scope,
key: key,
value: value,
});
}
}
@bindThis
public async getItem(userId: MiUser['id'], domain: string | null, scope: string[], key: string): Promise<MiRegistryItem | null> {
const query = this.registryItemsRepository.createQueryBuilder('item')
.where(domain == null ? 'item.domain IS NULL' : 'item.domain = :domain', { domain: domain })
.andWhere('item.userId = :userId', { userId: userId })
.andWhere('item.key = :key', { key: key })
.andWhere('item.scope = :scope', { scope: scope });
const item = await query.getOne();
return item;
}
@bindThis
public async getAllItemsOfScope(userId: MiUser['id'], domain: string | null, scope: string[]): Promise<MiRegistryItem[]> {
const query = this.registryItemsRepository.createQueryBuilder('item');
query.where(domain == null ? 'item.domain IS NULL' : 'item.domain = :domain', { domain: domain });
query.andWhere('item.userId = :userId', { userId: userId });
query.andWhere('item.scope = :scope', { scope: scope });
const items = await query.getMany();
return items;
}
@bindThis
public async getAllKeysOfScope(userId: MiUser['id'], domain: string | null, scope: string[]): Promise<string[]> {
const query = this.registryItemsRepository.createQueryBuilder('item');
query.select('item.key');
query.where(domain == null ? 'item.domain IS NULL' : 'item.domain = :domain', { domain: domain });
query.andWhere('item.userId = :userId', { userId: userId });
query.andWhere('item.scope = :scope', { scope: scope });
const items = await query.getMany();
return items.map(x => x.key);
}
@bindThis
public async getAllScopeAndDomains(userId: MiUser['id']): Promise<{ domain: string | null; scopes: string[][] }[]> {
const query = this.registryItemsRepository.createQueryBuilder('item')
.select(['item.scope', 'item.domain'])
.where('item.userId = :userId', { userId: userId });
const items = await query.getMany();
const res = [] as { domain: string | null; scopes: string[][] }[];
for (const item of items) {
const target = res.find(x => x.domain === item.domain);
if (target) {
if (target.scopes.some(scope => scope.join('.') === item.scope.join('.'))) continue;
target.scopes.push(item.scope);
} else {
res.push({
domain: item.domain,
scopes: [item.scope],
});
}
}
return res;
}
@bindThis
public async remove(userId: MiUser['id'], domain: string | null, scope: string[], key: string) {
const query = this.registryItemsRepository.createQueryBuilder().delete();
if (domain) {
query.where('domain = :domain', { domain: domain });
} else {
query.where('domain IS NULL');
}
query.andWhere('userId = :userId', { userId: userId });
query.andWhere('key = :key', { key: key });
query.andWhere('scope = :scope', { scope: scope });
await query.execute();
}
}
|