parent
							
								
									0a6e237d09
								
							
						
					
					
						commit
						b250456814
					
				
					 21 changed files with 55 additions and 16 deletions
				
			
		|  | @ -73,6 +73,7 @@ You should also include the user name that made the change. | ||||||
| - AVIF support @tamaina | - AVIF support @tamaina | ||||||
| - Add Cloudflare Turnstile CAPTCHA support @CyberRex0 | - Add Cloudflare Turnstile CAPTCHA support @CyberRex0 | ||||||
| - 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように | - 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように | ||||||
|  | - 非モデレーターでも、権限を持つロールをアサインされたユーザーはカスタム絵文字の追加、編集、削除を行えるように | ||||||
| - Server: signToActivityPubGet is set to true by default @syuilo | - Server: signToActivityPubGet is set to true by default @syuilo | ||||||
| - Server: improve syslog performance @syuilo | - Server: improve syslog performance @syuilo | ||||||
| - Server: Use undici instead of node-fetch and got @tamaina | - Server: Use undici instead of node-fetch and got @tamaina | ||||||
|  |  | ||||||
|  | @ -931,6 +931,7 @@ undefined: "未定義" | ||||||
| assign: "アサイン" | assign: "アサイン" | ||||||
| unassign: "アサインを解除" | unassign: "アサインを解除" | ||||||
| color: "色" | color: "色" | ||||||
|  | manageCustomEmojis: "カスタム絵文字の管理" | ||||||
| 
 | 
 | ||||||
| _role: | _role: | ||||||
|   new: "ロールの作成" |   new: "ロールの作成" | ||||||
|  | @ -958,6 +959,7 @@ _role: | ||||||
|     ltlAvailable: "ローカルタイムラインの閲覧" |     ltlAvailable: "ローカルタイムラインの閲覧" | ||||||
|     canPublicNote: "パブリック投稿の許可" |     canPublicNote: "パブリック投稿の許可" | ||||||
|     canInvite: "インスタンス招待コードの発行" |     canInvite: "インスタンス招待コードの発行" | ||||||
|  |     canManageCustomEmojis: "カスタム絵文字の管理" | ||||||
|     driveCapacity: "ドライブ容量" |     driveCapacity: "ドライブ容量" | ||||||
|     antennaMax: "アンテナの作成可能数" |     antennaMax: "アンテナの作成可能数" | ||||||
|   _condition: |   _condition: | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ export type RoleOptions = { | ||||||
| 	ltlAvailable: boolean; | 	ltlAvailable: boolean; | ||||||
| 	canPublicNote: boolean; | 	canPublicNote: boolean; | ||||||
| 	canInvite: boolean; | 	canInvite: boolean; | ||||||
|  | 	canManageCustomEmojis: boolean; | ||||||
| 	driveCapacityMb: number; | 	driveCapacityMb: number; | ||||||
| 	antennaLimit: number; | 	antennaLimit: number; | ||||||
| }; | }; | ||||||
|  | @ -26,6 +27,7 @@ export const DEFAULT_ROLE: RoleOptions = { | ||||||
| 	ltlAvailable: true, | 	ltlAvailable: true, | ||||||
| 	canPublicNote: true, | 	canPublicNote: true, | ||||||
| 	canInvite: false, | 	canInvite: false, | ||||||
|  | 	canManageCustomEmojis: false, | ||||||
| 	driveCapacityMb: 100, | 	driveCapacityMb: 100, | ||||||
| 	antennaLimit: 5, | 	antennaLimit: 5, | ||||||
| }; | }; | ||||||
|  | @ -182,6 +184,7 @@ export class RoleService implements OnApplicationShutdown { | ||||||
| 			ltlAvailable: getOptionValues('ltlAvailable').some(x => x === true), | 			ltlAvailable: getOptionValues('ltlAvailable').some(x => x === true), | ||||||
| 			canPublicNote: getOptionValues('canPublicNote').some(x => x === true), | 			canPublicNote: getOptionValues('canPublicNote').some(x => x === true), | ||||||
| 			canInvite: getOptionValues('canInvite').some(x => x === true), | 			canInvite: getOptionValues('canInvite').some(x => x === true), | ||||||
|  | 			canManageCustomEmojis: getOptionValues('canManageCustomEmojis').some(x => x === true), | ||||||
| 			driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')), | 			driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')), | ||||||
| 			antennaLimit: Math.max(...getOptionValues('antennaLimit')), | 			antennaLimit: Math.max(...getOptionValues('antennaLimit')), | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| } as const; | } as const; | ||||||
| 
 | 
 | ||||||
| export const paramDef = { | export const paramDef = { | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| 
 | 
 | ||||||
| 	errors: { | 	errors: { | ||||||
| 		noSuchFile: { | 		noSuchFile: { | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| 
 | 
 | ||||||
| 	errors: { | 	errors: { | ||||||
| 		noSuchEmoji: { | 		noSuchEmoji: { | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| } as const; | } as const; | ||||||
| 
 | 
 | ||||||
| export const paramDef = { | export const paramDef = { | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| 
 | 
 | ||||||
| 	errors: { | 	errors: { | ||||||
| 		noSuchEmoji: { | 		noSuchEmoji: { | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ import { QueueService } from '@/core/QueueService.js'; | ||||||
| export const meta = { | export const meta = { | ||||||
| 	secure: true, | 	secure: true, | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| } as const; | } as const; | ||||||
| 
 | 
 | ||||||
| export const paramDef = { | export const paramDef = { | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| 
 | 
 | ||||||
| 	res: { | 	res: { | ||||||
| 		type: 'array', | 		type: 'array', | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| 
 | 
 | ||||||
| 	res: { | 	res: { | ||||||
| 		type: 'array', | 		type: 'array', | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| } as const; | } as const; | ||||||
| 
 | 
 | ||||||
| export const paramDef = { | export const paramDef = { | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| } as const; | } as const; | ||||||
| 
 | 
 | ||||||
| export const paramDef = { | export const paramDef = { | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| } as const; | } as const; | ||||||
| 
 | 
 | ||||||
| export const paramDef = { | export const paramDef = { | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
| 
 | 
 | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| 	requireModerator: true, | 	requireRoleOption: 'canManageCustomEmojis', | ||||||
| 
 | 
 | ||||||
| 	errors: { | 	errors: { | ||||||
| 		noSuchEmoji: { | 		noSuchEmoji: { | ||||||
|  |  | ||||||
|  | @ -90,6 +90,19 @@ | ||||||
| 				</div> | 				</div> | ||||||
| 			</MkFolder> | 			</MkFolder> | ||||||
| 
 | 
 | ||||||
|  | 			<MkFolder> | ||||||
|  | 				<template #label>{{ i18n.ts._role._options.canManageCustomEmojis }}</template> | ||||||
|  | 				<template #suffix>{{ options_canManageCustomEmojis_useDefault ? i18n.ts._role.useBaseValue : (options_canManageCustomEmojis_value ? i18n.ts.yes : i18n.ts.no) }}</template> | ||||||
|  | 				<div class="_gaps"> | ||||||
|  | 					<MkSwitch v-model="options_canManageCustomEmojis_useDefault" :readonly="readonly"> | ||||||
|  | 						<template #label>{{ i18n.ts._role.useBaseValue }}</template> | ||||||
|  | 					</MkSwitch> | ||||||
|  | 					<MkSwitch v-model="options_canManageCustomEmojis_value" :disabled="options_canManageCustomEmojis_useDefault" :readonly="readonly"> | ||||||
|  | 						<template #label>{{ i18n.ts.enable }}</template> | ||||||
|  | 					</MkSwitch> | ||||||
|  | 				</div> | ||||||
|  | 			</MkFolder> | ||||||
|  | 
 | ||||||
| 			<MkFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts._role._options.driveCapacity }}</template> | 				<template #label>{{ i18n.ts._role._options.driveCapacity }}</template> | ||||||
| 				<template #suffix>{{ options_driveCapacityMb_useDefault ? i18n.ts._role.useBaseValue : (options_driveCapacityMb_value + 'MB') }}</template> | 				<template #suffix>{{ options_driveCapacityMb_useDefault ? i18n.ts._role.useBaseValue : (options_driveCapacityMb_value + 'MB') }}</template> | ||||||
|  | @ -175,6 +188,8 @@ let options_canPublicNote_useDefault = $ref(role?.options?.canPublicNote?.useDef | ||||||
| let options_canPublicNote_value = $ref(role?.options?.canPublicNote?.value ?? false); | let options_canPublicNote_value = $ref(role?.options?.canPublicNote?.value ?? false); | ||||||
| let options_canInvite_useDefault = $ref(role?.options?.canInvite?.useDefault ?? true); | let options_canInvite_useDefault = $ref(role?.options?.canInvite?.useDefault ?? true); | ||||||
| let options_canInvite_value = $ref(role?.options?.canInvite?.value ?? false); | let options_canInvite_value = $ref(role?.options?.canInvite?.value ?? false); | ||||||
|  | let options_canManageCustomEmojis_useDefault = $ref(role?.options?.canManageCustomEmojis?.useDefault ?? true); | ||||||
|  | let options_canManageCustomEmojis_value = $ref(role?.options?.canManageCustomEmojis?.value ?? false); | ||||||
| let options_driveCapacityMb_useDefault = $ref(role?.options?.driveCapacityMb?.useDefault ?? true); | let options_driveCapacityMb_useDefault = $ref(role?.options?.driveCapacityMb?.useDefault ?? true); | ||||||
| let options_driveCapacityMb_value = $ref(role?.options?.driveCapacityMb?.value ?? 0); | let options_driveCapacityMb_value = $ref(role?.options?.driveCapacityMb?.value ?? 0); | ||||||
| let options_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefault ?? true); | let options_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefault ?? true); | ||||||
|  | @ -192,6 +207,7 @@ function getOptions() { | ||||||
| 		ltlAvailable: { useDefault: options_ltlAvailable_useDefault, value: options_ltlAvailable_value }, | 		ltlAvailable: { useDefault: options_ltlAvailable_useDefault, value: options_ltlAvailable_value }, | ||||||
| 		canPublicNote: { useDefault: options_canPublicNote_useDefault, value: options_canPublicNote_value }, | 		canPublicNote: { useDefault: options_canPublicNote_useDefault, value: options_canPublicNote_value }, | ||||||
| 		canInvite: { useDefault: options_canInvite_useDefault, value: options_canInvite_value }, | 		canInvite: { useDefault: options_canInvite_useDefault, value: options_canInvite_value }, | ||||||
|  | 		canManageCustomEmojis: { useDefault: options_canManageCustomEmojis_useDefault, value: options_canManageCustomEmojis_value }, | ||||||
| 		driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value }, | 		driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value }, | ||||||
| 		antennaLimit: { useDefault: options_antennaLimit_useDefault, value: options_antennaLimit_value }, | 		antennaLimit: { useDefault: options_antennaLimit_useDefault, value: options_antennaLimit_value }, | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | @ -40,6 +40,14 @@ | ||||||
| 							</MkSwitch> | 							</MkSwitch> | ||||||
| 						</MkFolder> | 						</MkFolder> | ||||||
| 
 | 
 | ||||||
|  | 						<MkFolder> | ||||||
|  | 							<template #label>{{ i18n.ts._role._options.canManageCustomEmojis }}</template> | ||||||
|  | 							<template #suffix>{{ options_canManageCustomEmojis ? i18n.ts.yes : i18n.ts.no }}</template> | ||||||
|  | 							<MkSwitch v-model="options_canManageCustomEmojis"> | ||||||
|  | 								<template #label>{{ i18n.ts.enable }}</template> | ||||||
|  | 							</MkSwitch> | ||||||
|  | 						</MkFolder> | ||||||
|  | 
 | ||||||
| 						<MkFolder> | 						<MkFolder> | ||||||
| 							<template #label>{{ i18n.ts._role._options.driveCapacity }}</template> | 							<template #label>{{ i18n.ts._role._options.driveCapacity }}</template> | ||||||
| 							<template #suffix>{{ options_driveCapacityMb }}MB</template> | 							<template #suffix>{{ options_driveCapacityMb }}MB</template> | ||||||
|  | @ -90,6 +98,7 @@ let options_gtlAvailable = $ref(instance.baseRole.gtlAvailable); | ||||||
| let options_ltlAvailable = $ref(instance.baseRole.ltlAvailable); | let options_ltlAvailable = $ref(instance.baseRole.ltlAvailable); | ||||||
| let options_canPublicNote = $ref(instance.baseRole.canPublicNote); | let options_canPublicNote = $ref(instance.baseRole.canPublicNote); | ||||||
| let options_canInvite = $ref(instance.baseRole.canInvite); | let options_canInvite = $ref(instance.baseRole.canInvite); | ||||||
|  | let options_canManageCustomEmojis = $ref(instance.baseRole.canManageCustomEmojis); | ||||||
| let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb); | let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb); | ||||||
| let options_antennaLimit = $ref(instance.baseRole.antennaLimit); | let options_antennaLimit = $ref(instance.baseRole.antennaLimit); | ||||||
| 
 | 
 | ||||||
|  | @ -100,6 +109,7 @@ async function updateBaseRole() { | ||||||
| 			ltlAvailable: options_ltlAvailable, | 			ltlAvailable: options_ltlAvailable, | ||||||
| 			canPublicNote: options_canPublicNote, | 			canPublicNote: options_canPublicNote, | ||||||
| 			canInvite: options_canInvite, | 			canInvite: options_canInvite, | ||||||
|  | 			canManageCustomEmojis: options_canManageCustomEmojis, | ||||||
| 			driveCapacityMb: options_driveCapacityMb, | 			driveCapacityMb: options_driveCapacityMb, | ||||||
| 			antennaLimit: options_antennaLimit, | 			antennaLimit: options_antennaLimit, | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| <template> | <template> | ||||||
| <div> | <div> | ||||||
| 	<MkStickyContainer> | 	<MkStickyContainer> | ||||||
| 		<template #header><XHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template> | 		<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template> | ||||||
| 		<MkSpacer :content-max="900"> | 		<MkSpacer :content-max="900"> | ||||||
| 			<div class="ogwlenmc"> | 			<div class="ogwlenmc"> | ||||||
| 				<div v-if="tab === 'local'" class="local"> | 				<div v-if="tab === 'local'" class="local"> | ||||||
|  | @ -69,7 +69,6 @@ | ||||||
| 
 | 
 | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { computed, defineAsyncComponent, defineComponent, ref, shallowRef } from 'vue'; | import { computed, defineAsyncComponent, defineComponent, ref, shallowRef } from 'vue'; | ||||||
| import XHeader from './_header_.vue'; |  | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import MkInput from '@/components/MkInput.vue'; | import MkInput from '@/components/MkInput.vue'; | ||||||
| import MkPagination from '@/components/MkPagination.vue'; | import MkPagination from '@/components/MkPagination.vue'; | ||||||
|  | @ -305,6 +305,9 @@ export const routes = [{ | ||||||
| }, { | }, { | ||||||
| 	path: '/channels', | 	path: '/channels', | ||||||
| 	component: page(() => import('./pages/channels.vue')), | 	component: page(() => import('./pages/channels.vue')), | ||||||
|  | }, { | ||||||
|  | 	path: '/custom-emojis-manager', | ||||||
|  | 	component: page(() => import('./pages/custom-emojis-manager.vue')), | ||||||
| }, { | }, { | ||||||
| 	path: '/registry/keys/system/:path(*)?', | 	path: '/registry/keys/system/:path(*)?', | ||||||
| 	component: page(() => import('./pages/registry.keys.vue')), | 	component: page(() => import('./pages/registry.keys.vue')), | ||||||
|  | @ -331,7 +334,7 @@ export const routes = [{ | ||||||
| 	}, { | 	}, { | ||||||
| 		path: '/emojis', | 		path: '/emojis', | ||||||
| 		name: 'emojis', | 		name: 'emojis', | ||||||
| 		component: page(() => import('./pages/admin/emojis.vue')), | 		component: page(() => import('./pages/custom-emojis-manager.vue')), | ||||||
| 	}, { | 	}, { | ||||||
| 		path: '/queue', | 		path: '/queue', | ||||||
| 		name: 'queue', | 		name: 'queue', | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ export function openInstanceMenu(ev: MouseEvent) { | ||||||
| 			to: '/clicker', | 			to: '/clicker', | ||||||
| 			text: '🍪👈', | 			text: '🍪👈', | ||||||
| 			icon: 'ti ti-cookie', | 			icon: 'ti ti-cookie', | ||||||
| 		}, ($i && ($i.isRoot || $i.role.canInvite) && instance.disableRegistration) ? { | 		}, ($i && ($i.isAdmin || $i.role.canInvite) && instance.disableRegistration) ? { | ||||||
| 			text: i18n.ts.invite, | 			text: i18n.ts.invite, | ||||||
| 			icon: 'ti ti-user-plus', | 			icon: 'ti ti-user-plus', | ||||||
| 			action: () => { | 			action: () => { | ||||||
|  | @ -63,6 +63,11 @@ export function openInstanceMenu(ev: MouseEvent) { | ||||||
| 					}); | 					}); | ||||||
| 				}); | 				}); | ||||||
| 			}, | 			}, | ||||||
|  | 		} : undefined, ($i && ($i.isAdmin || $i.role.canManageCustomEmojis)) ? { | ||||||
|  | 			type: 'link', | ||||||
|  | 			to: '/custom-emojis-manager', | ||||||
|  | 			text: i18n.ts.manageCustomEmojis, | ||||||
|  | 			icon: 'ti ti-icons', | ||||||
| 		} : undefined], | 		} : undefined], | ||||||
| 	}, null, { | 	}, null, { | ||||||
| 		text: i18n.ts.help, | 		text: i18n.ts.help, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue