allow tokens to limit a user's rank
This commit is contained in:
parent
a4c816d07c
commit
70b85e5215
8 changed files with 72 additions and 4 deletions
22
locales/index.d.ts
vendored
22
locales/index.d.ts
vendored
|
|
@ -13511,6 +13511,28 @@ export interface Locale extends ILocale {
|
||||||
* Permissions
|
* Permissions
|
||||||
*/
|
*/
|
||||||
"permissions": string;
|
"permissions": string;
|
||||||
|
/**
|
||||||
|
* Override rank
|
||||||
|
*/
|
||||||
|
"overrideRank": string;
|
||||||
|
/**
|
||||||
|
* Overrides the user rank (admin, moderator, or user) for apps using this token.
|
||||||
|
*/
|
||||||
|
"overrideRankDescription": string;
|
||||||
|
"_ranks": {
|
||||||
|
/**
|
||||||
|
* Admin
|
||||||
|
*/
|
||||||
|
"admin": string;
|
||||||
|
/**
|
||||||
|
* Moderator
|
||||||
|
*/
|
||||||
|
"mod": string;
|
||||||
|
/**
|
||||||
|
* User
|
||||||
|
*/
|
||||||
|
"user": string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
declare const locales: {
|
declare const locales: {
|
||||||
[lang: string]: Locale;
|
[lang: string]: Locale;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import { id } from './util/id.js';
|
||||||
import { MiUser } from './User.js';
|
import { MiUser } from './User.js';
|
||||||
import { MiApp } from './App.js';
|
import { MiApp } from './App.js';
|
||||||
|
|
||||||
|
export const accessTokenRanks = ['user', 'mod', 'admin'] as const;
|
||||||
|
export type AccessTokenRank = typeof accessTokenRanks[number];
|
||||||
|
|
||||||
@Entity('access_token')
|
@Entity('access_token')
|
||||||
export class MiAccessToken {
|
export class MiAccessToken {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
|
|
@ -87,4 +90,11 @@ export class MiAccessToken {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
public fetched: boolean;
|
public fetched: boolean;
|
||||||
|
|
||||||
|
@Column('enum', {
|
||||||
|
enum: accessTokenRanks,
|
||||||
|
nullable: true,
|
||||||
|
comment: 'Limits the user\' rank (user, moderator, or admin) when using this token. If null (default), then uses the user\'s actual rank.',
|
||||||
|
})
|
||||||
|
public rank: AccessTokenRank | null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ export const paramDef = {
|
||||||
grantees: { type: 'array', uniqueItems: true, items: {
|
grantees: { type: 'array', uniqueItems: true, items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
} },
|
} },
|
||||||
|
rank: { type: 'string', enum: ['admin', 'mod', 'user'], nullable: true },
|
||||||
},
|
},
|
||||||
required: ['session', 'permission'],
|
required: ['session', 'permission'],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
@ -109,6 +110,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
description: ps.description,
|
description: ps.description,
|
||||||
iconUrl: ps.iconUrl,
|
iconUrl: ps.iconUrl,
|
||||||
permission: ps.permission,
|
permission: ps.permission,
|
||||||
|
rank: ps.rank,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Insert shared access grants
|
// Insert shared access grants
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,22 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<MkFolder v-if="$i?.isAdmin || $i?.isModerator">
|
||||||
|
<template #label>{{ i18n.ts.overrideRank }}</template>
|
||||||
|
<template #caption>{{ i18n.ts.overrideRankDescription }}</template>
|
||||||
|
|
||||||
|
<MkSelect v-if="$i?.isAdmin" v-model="rank">
|
||||||
|
<option value="admin">{{ i18n.ts._ranks.admin }}</option>
|
||||||
|
<option value="mod">{{ i18n.ts._ranks.mod }}</option>
|
||||||
|
<option value="user">{{ i18n.ts._ranks.user }}</option>
|
||||||
|
</MkSelect>
|
||||||
|
|
||||||
|
<MkSelect v-else v-model="rank">
|
||||||
|
<option value="mod">{{ i18n.ts._ranks.mod }}</option>
|
||||||
|
<option value="user">{{ i18n.ts._ranks.user }}</option>
|
||||||
|
</MkSelect>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder>
|
<MkFolder>
|
||||||
<template #label>{{ i18n.ts.permission }}</template>
|
<template #label>{{ i18n.ts.permission }}</template>
|
||||||
<template #caption>{{ i18n.ts.permissionsDescription }}</template>
|
<template #caption>{{ i18n.ts.permissionsDescription }}</template>
|
||||||
|
|
@ -82,9 +98,10 @@ import MkButton from './MkButton.vue';
|
||||||
import MkInfo from './MkInfo.vue';
|
import MkInfo from './MkInfo.vue';
|
||||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { iAmAdmin } from '@/i.js';
|
import { $i, iAmAdmin } from '@/i.js';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||||
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { instance } from '@/instance';
|
import { instance } from '@/instance';
|
||||||
|
|
||||||
|
|
@ -102,7 +119,7 @@ const props = withDefaults(defineProps<{
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'closed'): void;
|
(ev: 'closed'): void;
|
||||||
(ev: 'done', result: { name: string | null, permissions: string[], grantees: string[] }): void;
|
(ev: 'done', result: { name: string | null, permissions: string[], grantees: string[], rank: string }): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const defaultPermissions = Misskey.permissions.filter(p => !p.startsWith('read:admin') && !p.startsWith('write:admin'));
|
const defaultPermissions = Misskey.permissions.filter(p => !p.startsWith('read:admin') && !p.startsWith('write:admin'));
|
||||||
|
|
@ -113,6 +130,12 @@ const name = ref(props.initialName);
|
||||||
const permissionSwitches = ref({} as Record<(typeof Misskey.permissions)[number], boolean>);
|
const permissionSwitches = ref({} as Record<(typeof Misskey.permissions)[number], boolean>);
|
||||||
const permissionSwitchesForAdmin = ref({} as Record<(typeof Misskey.permissions)[number], boolean>);
|
const permissionSwitchesForAdmin = ref({} as Record<(typeof Misskey.permissions)[number], boolean>);
|
||||||
const grantees = ref<Misskey.entities.User[]>([]);
|
const grantees = ref<Misskey.entities.User[]>([]);
|
||||||
|
const rank = ref<'admin' | 'mod' | 'user'>(
|
||||||
|
$i?.isAdmin
|
||||||
|
? 'admin'
|
||||||
|
: $i?.isModerator
|
||||||
|
? 'mod'
|
||||||
|
: 'user');
|
||||||
|
|
||||||
if (props.initialPermissions) {
|
if (props.initialPermissions) {
|
||||||
for (const kind of props.initialPermissions) {
|
for (const kind of props.initialPermissions) {
|
||||||
|
|
@ -138,6 +161,7 @@ function ok(): void {
|
||||||
...(iAmAdmin ? Object.keys(permissionSwitchesForAdmin.value).filter(p => permissionSwitchesForAdmin.value[p]) : []),
|
...(iAmAdmin ? Object.keys(permissionSwitchesForAdmin.value).filter(p => permissionSwitchesForAdmin.value[p]) : []),
|
||||||
],
|
],
|
||||||
grantees: grantees.value.map(g => g.id),
|
grantees: grantees.value.map(g => g.id),
|
||||||
|
rank: rank.value,
|
||||||
});
|
});
|
||||||
dialog.value?.close();
|
dialog.value?.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,13 @@ const pagination = {
|
||||||
function generateToken() {
|
function generateToken() {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
||||||
done: async result => {
|
done: async result => {
|
||||||
const { name, permissions, grantees } = result;
|
const { name, permissions, grantees, rank } = result;
|
||||||
const { token } = await misskeyApi('miauth/gen-token', {
|
const { token } = await misskeyApi('miauth/gen-token', {
|
||||||
session: null,
|
session: null,
|
||||||
name: name,
|
name: name,
|
||||||
permission: permissions,
|
permission: permissions,
|
||||||
grantees: grantees,
|
grantees: grantees,
|
||||||
|
rank: rank,
|
||||||
});
|
});
|
||||||
|
|
||||||
os.alert({
|
os.alert({
|
||||||
|
|
|
||||||
|
|
@ -109,11 +109,12 @@ export async function authorizePlugin(plugin: Plugin) {
|
||||||
initialPermissions: plugin.permissions,
|
initialPermissions: plugin.permissions,
|
||||||
}, {
|
}, {
|
||||||
done: async result => {
|
done: async result => {
|
||||||
const { name, permissions } = result;
|
const { name, permissions, rank } = result;
|
||||||
const { token } = await misskeyApi('miauth/gen-token', {
|
const { token } = await misskeyApi('miauth/gen-token', {
|
||||||
session: null,
|
session: null,
|
||||||
name: name,
|
name: name,
|
||||||
permission: permissions,
|
permission: permissions,
|
||||||
|
rank: rank,
|
||||||
});
|
});
|
||||||
res(token);
|
res(token);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -26379,6 +26379,8 @@ export type operations = {
|
||||||
iconUrl?: string | null;
|
iconUrl?: string | null;
|
||||||
permission: string[];
|
permission: string[];
|
||||||
grantees?: string[];
|
grantees?: string[];
|
||||||
|
/** @enum {string|null} */
|
||||||
|
rank?: 'admin' | 'mod' | 'user';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -692,3 +692,9 @@ noSharedAccess: "You have not been granted shared access to any accounts"
|
||||||
expand: "Expand"
|
expand: "Expand"
|
||||||
collapse: "Collapse"
|
collapse: "Collapse"
|
||||||
permissions: "Permissions"
|
permissions: "Permissions"
|
||||||
|
overrideRank: "Override rank"
|
||||||
|
overrideRankDescription: "Overrides the user rank (admin, moderator, or user) for apps using this token."
|
||||||
|
_ranks:
|
||||||
|
admin: "Admin"
|
||||||
|
mod: "Moderator"
|
||||||
|
user: "User"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue