summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-05-29 22:20:21 -0400
committerHazelnoot <acomputerdog@gmail.com>2025-05-29 22:20:21 -0400
commit979c7628b1d2b21bd9dd9d13ec0110bde883f074 (patch)
treeece2afb731c98725b8bfaa8f6eb123ef7a7d688e
parentimplement SkBadgeStrip (diff)
downloadsharkey-979c7628b1d2b21bd9dd9d13ec0110bde883f074.tar.gz
sharkey-979c7628b1d2b21bd9dd9d13ec0110bde883f074.tar.bz2
sharkey-979c7628b1d2b21bd9dd9d13ec0110bde883f074.zip
disable status badge strip in admin-user and instance-info
-rw-r--r--locales/index.d.ts28
-rw-r--r--packages/backend/src/core/UtilityService.ts9
-rw-r--r--packages/backend/src/core/entities/InstanceEntityService.ts1
-rw-r--r--packages/backend/src/models/json-schema/federation-instance.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-user.ts6
-rw-r--r--packages/frontend/src/pages/admin-user.vue103
-rw-r--r--packages/frontend/src/pages/instance-info.vue58
-rw-r--r--packages/misskey-js/src/autogen/types.ts2
-rw-r--r--sharkey-locales/en-US.yml9
9 files changed, 211 insertions, 9 deletions
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 2392d51c45..2f3bc664ff 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -13146,9 +13146,37 @@ export interface Locale extends ILocale {
*/
"lastPosted": ParameterizedString<"at">;
/**
+ * NSFW
+ */
+ "nsfw": string;
+ /**
* Raw
*/
"raw": string;
+ /**
+ * CW
+ */
+ "cw": string;
+ /**
+ * Media Silenced
+ */
+ "mediaSilenced": string;
+ /**
+ * Bubble
+ */
+ "bubble": string;
+ /**
+ * Verified
+ */
+ "verified": string;
+ /**
+ * Not Verified
+ */
+ "notVerified": string;
+ /**
+ * Hibernated
+ */
+ "hibernated": string;
}
declare const locales: {
[lang: string]: Locale;
diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts
index 170afc72dc..ee17906d55 100644
--- a/packages/backend/src/core/UtilityService.ts
+++ b/packages/backend/src/core/UtilityService.ts
@@ -68,6 +68,15 @@ export class UtilityService {
}
@bindThis
+ public isBubbledHost(host: string | null): boolean {
+ if (host == null) return false;
+
+ // TODO remove null conditional after merging lab/persisted-instance-blocks
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ return this.meta.bubbleInstances?.includes(host);
+ }
+
+ @bindThis
public concatNoteContentsForKeyWordCheck(content: {
cw?: string | null;
text?: string | null;
diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts
index fcc9bed3bd..08a7765d40 100644
--- a/packages/backend/src/core/entities/InstanceEntityService.ts
+++ b/packages/backend/src/core/entities/InstanceEntityService.ts
@@ -62,6 +62,7 @@ export class InstanceEntityService {
rejectReports: instance.rejectReports,
rejectQuotes: instance.rejectQuotes,
moderationNote: iAmModerator ? instance.moderationNote : null,
+ isBubbled: this.utilityService.isBubbledHost(instance.host),
};
}
diff --git a/packages/backend/src/models/json-schema/federation-instance.ts b/packages/backend/src/models/json-schema/federation-instance.ts
index 57d4466ffa..fd6eddf594 100644
--- a/packages/backend/src/models/json-schema/federation-instance.ts
+++ b/packages/backend/src/models/json-schema/federation-instance.ts
@@ -135,5 +135,9 @@ export const packedFederationInstanceSchema = {
type: 'string',
optional: true, nullable: true,
},
+ isBubbled: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
},
} as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts
index 1579719246..6a77fc177f 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts
@@ -122,6 +122,10 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
+ isAdministrator: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
isSystem: {
type: 'boolean',
optional: false, nullable: false,
@@ -257,6 +261,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const isModerator = await this.roleService.isModerator(user);
+ const isAdministrator = await this.roleService.isAdministrator(user);
const isSilenced = user.isSilenced || !(await this.roleService.getUserPolicies(user.id)).canPublicNote;
const _me = await this.usersRepository.findOneByOrFail({ id: me.id });
@@ -289,6 +294,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
mutedInstances: profile.mutedInstances,
notificationRecieveConfig: profile.notificationRecieveConfig,
isModerator: isModerator,
+ isAdministrator: isAdministrator,
isSystem: isSystemAccount(user),
isSilenced: isSilenced,
isSuspended: user.isSuspended,
diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue
index 63352f6ca3..f7db436bc8 100644
--- a/packages/frontend/src/pages/admin-user.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -20,16 +20,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<span class="_monospace">{{ user.id }}</span>
<button v-tooltip="i18n.ts.copy" class="_textButton" style="margin-left: 0.5em;" @click="copyToClipboard(user.id)"><i class="ti ti-copy"></i></button>
</span>
- <span class="state">
- <span v-if="!approved" class="silenced">{{ i18n.ts.notApproved }}</span>
- <span v-if="approved && !user.host" class="moderator">{{ i18n.ts.approved }}</span>
- <span v-if="suspended" class="suspended">{{ i18n.ts.suspended }}</span>
- <span v-if="silenced" class="silenced">{{ i18n.ts.silenced }}</span>
- <span v-if="moderator" class="moderator">{{ i18n.ts.moderator }}</span>
- </span>
</div>
</div>
+ <SkBadgeStrip v-if="badges.length > 0" :badges="badges"></SkBadgeStrip>
+
<MkInfo v-if="isSystem">{{ i18n.ts.isSystemAccount }}</MkInfo>
<MkFolder v-if="!isSystem">
@@ -248,6 +243,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, defineAsyncComponent, watch, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { url } from '@@/js/config.js';
+import type { Badge } from '@/components/SkBadgeStrip.vue';
import MkChart from '@/components/MkChart.vue';
import MkObjectView from '@/components/MkObjectView.vue';
import MkTextarea from '@/components/MkTextarea.vue';
@@ -272,6 +268,7 @@ import MkPagination from '@/components/MkPagination.vue';
import MkInput from '@/components/MkInput.vue';
import MkNumber from '@/components/MkNumber.vue';
import { copyToClipboard } from '@/utility/copy-to-clipboard';
+import SkBadgeStrip from '@/components/SkBadgeStrip.vue';
const props = withDefaults(defineProps<{
userId: string;
@@ -304,6 +301,98 @@ const filesPagination = {
})),
};
+const badges = computed(() => {
+ const arr: Badge[] = [];
+ if (info.value && user.value) {
+ if (info.value.isSuspended) {
+ arr.push({
+ key: 'suspended',
+ label: i18n.ts.suspended,
+ style: 'error',
+ });
+ }
+
+ if (info.value.isSilenced) {
+ arr.push({
+ key: 'silenced',
+ label: i18n.ts.silenced,
+ style: 'warning',
+ });
+ }
+
+ if (info.value.alwaysMarkNsfw) {
+ arr.push({
+ key: 'nsfw',
+ label: i18n.ts.nsfw,
+ style: 'warning',
+ });
+ }
+
+ if (user.value.mandatoryCW) {
+ arr.push({
+ key: 'cw',
+ label: i18n.ts.cw,
+ style: 'warning',
+ });
+ }
+
+ if (info.value.isHibernated) {
+ arr.push({
+ key: 'hibernated',
+ label: i18n.ts.hibernated,
+ style: 'neutral',
+ });
+ }
+
+ if (info.value.isAdministrator) {
+ arr.push({
+ key: 'admin',
+ label: i18n.ts.administrator,
+ style: 'success',
+ });
+ } else if (info.value.isModerator) {
+ arr.push({
+ key: 'mod',
+ label: i18n.ts.moderator,
+ style: 'success',
+ });
+ }
+
+ if (user.value.host == null) {
+ if (info.value.email) {
+ if (info.value.emailVerified) {
+ arr.push({
+ key: 'verified',
+ label: i18n.ts.verified,
+ style: 'success',
+ });
+ } else {
+ arr.push({
+ key: 'not_verified',
+ label: i18n.ts.notVerified,
+ style: 'success',
+ });
+ }
+ }
+
+ if (info.value.approved) {
+ arr.push({
+ key: 'approved',
+ label: i18n.ts.approved,
+ style: 'success',
+ });
+ } else {
+ arr.push({
+ key: 'not_approved',
+ label: i18n.ts.notApproved,
+ style: 'warning',
+ });
+ }
+ }
+ }
+ return arr;
+});
+
const announcementsStatus = ref<'active' | 'archived'>('active');
const announcementsPagination = {
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index 5d14b6bf2c..356bb4273b 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -24,6 +24,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</span>
</div>
</div>
+
+ <SkBadgeStrip v-if="badges.length > 0" :badges="badges"></SkBadgeStrip>
+
<MkFolder>
<template #icon><i class="ph-list-bullets ph-bold ph-lg"></i></template>
<template #label>{{ i18n.ts.details }}</template>
@@ -200,10 +203,11 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { ref, computed, watch } from 'vue';
+import { ref, computed, watch, useCssModule } from 'vue';
import * as Misskey from 'misskey-js';
import type { ChartSrc } from '@/components/MkChart.vue';
import type { Paging } from '@/components/MkPagination.vue';
+import type { Badge } from '@/components/SkBadgeStrip.vue';
import MkChart from '@/components/MkChart.vue';
import MkObjectView from '@/components/MkObjectView.vue';
import FormLink from '@/components/form/link.vue';
@@ -230,6 +234,9 @@ import { copyToClipboard } from '@/utility/copy-to-clipboard';
import { acct } from '@/filters/user';
import MkFolder from '@/components/MkFolder.vue';
import MkNumber from '@/components/MkNumber.vue';
+import SkBadgeStrip from '@/components/SkBadgeStrip.vue';
+
+const $style = useCssModule();
const props = defineProps<{
host: string;
@@ -266,6 +273,55 @@ const isBaseBlocked = computed(() => meta.value && baseDomains.value.some(d => m
const isBaseSilenced = computed(() => meta.value && baseDomains.value.some(d => meta.value?.silencedHosts.includes(d)));
const isBaseMediaSilenced = computed(() => meta.value && baseDomains.value.some(d => meta.value?.mediaSilencedHosts.includes(d)));
+const badges = computed(() => {
+ const arr: Badge[] = [];
+ if (instance.value) {
+ if (instance.value.isBlocked) {
+ arr.push({
+ key: 'blocked',
+ label: i18n.ts.blocked,
+ style: 'error',
+ });
+ }
+ if (instance.value.isSuspended) {
+ arr.push({
+ key: 'suspended',
+ label: i18n.ts.suspended,
+ style: 'error',
+ });
+ }
+ if (instance.value.isSilenced) {
+ arr.push({
+ key: 'silenced',
+ label: i18n.ts.silenced,
+ style: 'warning',
+ });
+ }
+ if (instance.value.isMediaSilenced) {
+ arr.push({
+ key: 'media_silenced',
+ label: i18n.ts.mediaSilenced,
+ style: 'warning',
+ });
+ }
+ if (instance.value.isNSFW) {
+ arr.push({
+ key: 'nsfw',
+ label: i18n.ts.nsfw,
+ style: 'warning',
+ });
+ }
+ if (instance.value.isBubbled) {
+ arr.push({
+ key: 'bubbled',
+ label: i18n.ts.bubble,
+ style: 'success',
+ });
+ }
+ }
+ return arr;
+});
+
const usersPagination = {
endpoint: iAmModerator ? 'admin/show-users' : 'users',
limit: 10,
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 55302960dc..13fc56ca53 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -5294,6 +5294,7 @@ export type components = {
rejectReports: boolean;
rejectQuotes: boolean;
moderationNote?: string | null;
+ isBubbled: boolean;
};
GalleryPost: {
/**
@@ -11209,6 +11210,7 @@ export type operations = {
}]>;
};
isModerator: boolean;
+ isAdministrator: boolean;
isSystem: boolean;
isSilenced: boolean;
isSuspended: boolean;
diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml
index 586203099f..e219872b71 100644
--- a/sharkey-locales/en-US.yml
+++ b/sharkey-locales/en-US.yml
@@ -594,4 +594,11 @@ followingPub: "Following (Pub)"
followersSub: "Followers (Sub)"
wellKnownResources: "Well-known resources"
lastPosted: "Last posted: {at}"
-raw: 'Raw'
+nsfw: "NSFW"
+raw: "Raw"
+cw: "CW"
+mediaSilenced: "Media Silenced"
+bubble: "Bubble"
+verified: "Verified"
+notVerified: "Not Verified"
+hibernated: "Hibernated"