summaryrefslogtreecommitdiff
path: root/src/server/api
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-01-11 20:38:34 +0900
committerGitHub <noreply@github.com>2021-01-11 20:38:34 +0900
commit6c975275f82c79eed2c7757d55283c95d23ca5b8 (patch)
tree2871e4c3a1a67295ea5c3e19b9136ae79a17088c /src/server/api
parentfix context menu (diff)
downloadsharkey-6c975275f82c79eed2c7757d55283c95d23ca5b8.tar.gz
sharkey-6c975275f82c79eed2c7757d55283c95d23ca5b8.tar.bz2
sharkey-6c975275f82c79eed2c7757d55283c95d23ca5b8.zip
Registry (#7073)
* wip * wip * wip * wip * wip * Update registry.value.vue * wip * wip * wip * wip * typo
Diffstat (limited to 'src/server/api')
-rw-r--r--src/server/api/api-handler.ts5
-rw-r--r--src/server/api/endpoints/i.ts25
-rw-r--r--src/server/api/endpoints/i/notifications.ts2
-rw-r--r--src/server/api/endpoints/i/registry/get-all.ts33
-rw-r--r--src/server/api/endpoints/i/registry/get-detail.ts48
-rw-r--r--src/server/api/endpoints/i/registry/get.ts45
-rw-r--r--src/server/api/endpoints/i/registry/keys-with-type.ts41
-rw-r--r--src/server/api/endpoints/i/registry/keys.ts28
-rw-r--r--src/server/api/endpoints/i/registry/remove.ts45
-rw-r--r--src/server/api/endpoints/i/registry/scopes.ts30
-rw-r--r--src/server/api/endpoints/i/registry/set.ts61
-rw-r--r--src/server/api/endpoints/i/update-client-setting.ts40
12 files changed, 359 insertions, 44 deletions
diff --git a/src/server/api/api-handler.ts b/src/server/api/api-handler.ts
index 7fbc200fc0..80a4fd97c8 100644
--- a/src/server/api/api-handler.ts
+++ b/src/server/api/api-handler.ts
@@ -11,7 +11,7 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => {
const reply = (x?: any, y?: ApiError) => {
if (x == null) {
ctx.status = 204;
- } else if (typeof x === 'number') {
+ } else if (typeof x === 'number' && y) {
ctx.status = x;
ctx.body = {
error: {
@@ -23,7 +23,8 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => {
}
};
} else {
- ctx.body = x;
+ // 文字列を返す場合は、JSON.stringify通さないとJSONと認識されない
+ ctx.body = typeof x === 'string' ? JSON.stringify(x) : x;
}
res();
};
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index bceb9548ef..3d0c092adb 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -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
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index fd355dab83..0e09bc73fd 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -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)
diff --git a/src/server/api/endpoints/i/registry/get-all.ts b/src/server/api/endpoints/i/registry/get-all.ts
new file mode 100644
index 0000000000..ce8653f22b
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/get-all.ts
@@ -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;
+});
diff --git a/src/server/api/endpoints/i/registry/get-detail.ts b/src/server/api/endpoints/i/registry/get-detail.ts
new file mode 100644
index 0000000000..441833d3d7
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/get-detail.ts
@@ -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,
+ };
+});
diff --git a/src/server/api/endpoints/i/registry/get.ts b/src/server/api/endpoints/i/registry/get.ts
new file mode 100644
index 0000000000..275e660cb6
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/get.ts
@@ -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;
+});
diff --git a/src/server/api/endpoints/i/registry/keys-with-type.ts b/src/server/api/endpoints/i/registry/keys-with-type.ts
new file mode 100644
index 0000000000..06d77acbeb
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/keys-with-type.ts
@@ -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;
+});
diff --git a/src/server/api/endpoints/i/registry/keys.ts b/src/server/api/endpoints/i/registry/keys.ts
new file mode 100644
index 0000000000..e4dd5044b4
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/keys.ts
@@ -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);
+});
diff --git a/src/server/api/endpoints/i/registry/remove.ts b/src/server/api/endpoints/i/registry/remove.ts
new file mode 100644
index 0000000000..e73444efd2
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/remove.ts
@@ -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);
+});
diff --git a/src/server/api/endpoints/i/registry/scopes.ts b/src/server/api/endpoints/i/registry/scopes.ts
new file mode 100644
index 0000000000..8b0e1a7fd8
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/scopes.ts
@@ -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;
+});
diff --git a/src/server/api/endpoints/i/registry/set.ts b/src/server/api/endpoints/i/registry/set.ts
new file mode 100644
index 0000000000..c732cfc8f5
--- /dev/null
+++ b/src/server/api/endpoints/i/registry/set.ts
@@ -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
+ });
+});
diff --git a/src/server/api/endpoints/i/update-client-setting.ts b/src/server/api/endpoints/i/update-client-setting.ts
deleted file mode 100644
index 5143d3d9ba..0000000000
--- a/src/server/api/endpoints/i/update-client-setting.ts
+++ /dev/null
@@ -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
- });
-});