Registry (#7073)
* wip * wip * wip * wip * wip * Update registry.value.vue * wip * wip * wip * wip * typo
This commit is contained in:
parent
1286dee1ab
commit
6c975275f8
37 changed files with 1017 additions and 100 deletions
|
@ -1,5 +1,7 @@
|
|||
import define from '../define';
|
||||
import { Users } from '../../../models';
|
||||
import { RegistryItems, UserProfiles, Users } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
import { genId } from '../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -22,6 +24,27 @@ export const meta = {
|
|||
export default define(meta, async (ps, user, token) => {
|
||||
const isSecure = token == null;
|
||||
|
||||
// TODO: そのうち消す
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
for (const [k, v] of Object.entries(profile.clientData)) {
|
||||
await RegistryItems.insert({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
userId: user.id,
|
||||
domain: null,
|
||||
scope: ['client', 'base'],
|
||||
key: k,
|
||||
value: v
|
||||
});
|
||||
}
|
||||
await UserProfiles.createQueryBuilder().update()
|
||||
.set({
|
||||
clientData: {},
|
||||
})
|
||||
.where('userId = :id', { id: user.id })
|
||||
.execute();
|
||||
|
||||
return await Users.pack(user, user, {
|
||||
detail: true,
|
||||
includeSecrets: isSecure
|
||||
|
|
|
@ -80,7 +80,7 @@ export default define(meta, async (ps, user) => {
|
|||
.where('muting.muterId = :muterId', { muterId: user.id });
|
||||
|
||||
const suspendedQuery = Users.createQueryBuilder('users')
|
||||
.select('id')
|
||||
.select('users.id')
|
||||
.where('users.isSuspended = TRUE');
|
||||
|
||||
const query = makePaginationQuery(Notifications.createQueryBuilder('notification'), ps.sinceId, ps.untilId)
|
||||
|
|
33
src/server/api/endpoints/i/registry/get-all.ts
Normal file
33
src/server/api/endpoints/i/registry/get-all.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const items = await query.getMany();
|
||||
|
||||
const res = {} as Record<string, any>;
|
||||
|
||||
for (const item of items) {
|
||||
res[item.key] = item.value;
|
||||
}
|
||||
|
||||
return res;
|
||||
});
|
48
src/server/api/endpoints/i/registry/get-detail.ts
Normal file
48
src/server/api/endpoints/i/registry/get-detail.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
import { ApiError } from '../../../error';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
key: {
|
||||
validator: $.str
|
||||
},
|
||||
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
|
||||
errors: {
|
||||
noSuchKey: {
|
||||
message: 'No such key.',
|
||||
code: 'NO_SUCH_KEY',
|
||||
id: '97a1e8e7-c0f7-47d2-957a-92e61256e01a'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.key = :key', { key: ps.key })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const item = await query.getOne();
|
||||
|
||||
if (item == null) {
|
||||
throw new ApiError(meta.errors.noSuchKey);
|
||||
}
|
||||
|
||||
return {
|
||||
updatedAt: item.updatedAt,
|
||||
value: item.value,
|
||||
};
|
||||
});
|
45
src/server/api/endpoints/i/registry/get.ts
Normal file
45
src/server/api/endpoints/i/registry/get.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
import { ApiError } from '../../../error';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
key: {
|
||||
validator: $.str
|
||||
},
|
||||
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
|
||||
errors: {
|
||||
noSuchKey: {
|
||||
message: 'No such key.',
|
||||
code: 'NO_SUCH_KEY',
|
||||
id: 'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.key = :key', { key: ps.key })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const item = await query.getOne();
|
||||
|
||||
if (item == null) {
|
||||
throw new ApiError(meta.errors.noSuchKey);
|
||||
}
|
||||
|
||||
return item.value;
|
||||
});
|
41
src/server/api/endpoints/i/registry/keys-with-type.ts
Normal file
41
src/server/api/endpoints/i/registry/keys-with-type.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const items = await query.getMany();
|
||||
|
||||
const res = {} as Record<string, string>;
|
||||
|
||||
for (const item of items) {
|
||||
const type = typeof item.value;
|
||||
res[item.key] =
|
||||
item.value === null ? 'null' :
|
||||
Array.isArray(item.value) ? 'array' :
|
||||
type === 'number' ? 'number' :
|
||||
type === 'string' ? 'string' :
|
||||
type === 'boolean' ? 'boolean' :
|
||||
type === 'object' ? 'object' :
|
||||
null as never;
|
||||
}
|
||||
|
||||
return res;
|
||||
});
|
28
src/server/api/endpoints/i/registry/keys.ts
Normal file
28
src/server/api/endpoints/i/registry/keys.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.select('item.key')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const items = await query.getMany();
|
||||
|
||||
return items.map(x => x.key);
|
||||
});
|
45
src/server/api/endpoints/i/registry/remove.ts
Normal file
45
src/server/api/endpoints/i/registry/remove.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
import { ApiError } from '../../../error';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
key: {
|
||||
validator: $.str
|
||||
},
|
||||
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
|
||||
errors: {
|
||||
noSuchKey: {
|
||||
message: 'No such key.',
|
||||
code: 'NO_SUCH_KEY',
|
||||
id: '1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.key = :key', { key: ps.key })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const item = await query.getOne();
|
||||
|
||||
if (item == null) {
|
||||
throw new ApiError(meta.errors.noSuchKey);
|
||||
}
|
||||
|
||||
RegistryItems.remove(item);
|
||||
});
|
30
src/server/api/endpoints/i/registry/scopes.ts
Normal file
30
src/server/api/endpoints/i/registry/scopes.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.select('item.scope')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id });
|
||||
|
||||
const items = await query.getMany();
|
||||
|
||||
const res = [] as string[][];
|
||||
|
||||
for (const item of items) {
|
||||
if (res.some(scope => scope.join('.') === item.scope.join('.'))) continue;
|
||||
res.push(item.scope);
|
||||
}
|
||||
|
||||
return res;
|
||||
});
|
61
src/server/api/endpoints/i/registry/set.ts
Normal file
61
src/server/api/endpoints/i/registry/set.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
import $ from 'cafy';
|
||||
import { publishMainStream } from '../../../../../services/stream';
|
||||
import define from '../../../define';
|
||||
import { RegistryItems } from '../../../../../models';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
key: {
|
||||
validator: $.str.min(1)
|
||||
},
|
||||
|
||||
value: {
|
||||
validator: $.nullable.any
|
||||
},
|
||||
|
||||
scope: {
|
||||
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
|
||||
default: [],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = RegistryItems.createQueryBuilder('item')
|
||||
.where('item.domain IS NULL')
|
||||
.andWhere('item.userId = :userId', { userId: user.id })
|
||||
.andWhere('item.key = :key', { key: ps.key })
|
||||
.andWhere('item.scope = :scope', { scope: ps.scope });
|
||||
|
||||
const existingItem = await query.getOne();
|
||||
|
||||
if (existingItem) {
|
||||
await RegistryItems.update(existingItem.id, {
|
||||
updatedAt: new Date(),
|
||||
value: ps.value
|
||||
});
|
||||
} else {
|
||||
await RegistryItems.insert({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
userId: user.id,
|
||||
domain: null,
|
||||
scope: ps.scope,
|
||||
key: ps.key,
|
||||
value: ps.value
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
|
||||
publishMainStream(user.id, 'registryUpdated', {
|
||||
scope: ps.scope,
|
||||
key: ps.key,
|
||||
value: ps.value
|
||||
});
|
||||
});
|
|
@ -1,40 +0,0 @@
|
|||
import $ from 'cafy';
|
||||
import { publishMainStream } from '../../../../services/stream';
|
||||
import define from '../../define';
|
||||
import { UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
|
||||
secure: true,
|
||||
|
||||
params: {
|
||||
name: {
|
||||
validator: $.str.match(/^[a-zA-Z]+$/)
|
||||
},
|
||||
|
||||
value: {
|
||||
validator: $.nullable.any
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
|
||||
await UserProfiles.createQueryBuilder().update()
|
||||
.set({
|
||||
clientData: Object.assign(profile.clientData, {
|
||||
[ps.name]: ps.value
|
||||
}),
|
||||
})
|
||||
.where('userId = :id', { id: user.id })
|
||||
.execute();
|
||||
|
||||
// Publish event
|
||||
publishMainStream(user.id, 'clientSettingUpdated', {
|
||||
key: ps.name,
|
||||
value: ps.value
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue