Merge branch 'feat/antenna_limit' into 'develop'
feat: antenna limit Co-authored-by: 老周部落 <laozhoubuluo@gmail.com> Closes #10894 See merge request firefish/firefish!10740
This commit is contained in:
commit
d1817d9a22
13 changed files with 72 additions and 2 deletions
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
Breaking changes are indicated by the :warning: icon.
|
Breaking changes are indicated by the :warning: icon.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Added `antennaLimit` field to the response of `meta` and `admin/meta`, and the request of `admin/update-meta` (optional).
|
||||||
|
|
||||||
## v20240413
|
## v20240413
|
||||||
|
|
||||||
- :warning: Removed `patrons` endpoint.
|
- :warning: Removed `patrons` endpoint.
|
||||||
|
|
|
@ -394,6 +394,7 @@ enableRegistration: "Enable new user registration"
|
||||||
invite: "Invite"
|
invite: "Invite"
|
||||||
driveCapacityPerLocalAccount: "Drive capacity per local user"
|
driveCapacityPerLocalAccount: "Drive capacity per local user"
|
||||||
driveCapacityPerRemoteAccount: "Drive capacity per remote user"
|
driveCapacityPerRemoteAccount: "Drive capacity per remote user"
|
||||||
|
antennaLimit: "The maximum number of antennas that each user can create"
|
||||||
inMb: "In megabytes"
|
inMb: "In megabytes"
|
||||||
iconUrl: "Icon URL"
|
iconUrl: "Icon URL"
|
||||||
bannerUrl: "Banner image URL"
|
bannerUrl: "Banner image URL"
|
||||||
|
|
|
@ -340,6 +340,7 @@ invite: "邀请"
|
||||||
driveCapacityPerLocalAccount: "每个本地用户的网盘容量"
|
driveCapacityPerLocalAccount: "每个本地用户的网盘容量"
|
||||||
driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
|
driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
|
||||||
inMb: "以兆字节 (MegaByte) 为单位"
|
inMb: "以兆字节 (MegaByte) 为单位"
|
||||||
|
antennaLimit: "每个用户最多可以创建的天线数量"
|
||||||
iconUrl: "图标 URL"
|
iconUrl: "图标 URL"
|
||||||
bannerUrl: "横幅图 URL"
|
bannerUrl: "横幅图 URL"
|
||||||
backgroundImageUrl: "背景图 URL"
|
backgroundImageUrl: "背景图 URL"
|
||||||
|
|
1
packages/backend-rs/index.d.ts
vendored
1
packages/backend-rs/index.d.ts
vendored
|
@ -492,6 +492,7 @@ export interface Meta {
|
||||||
recaptchaSecretKey: string | null
|
recaptchaSecretKey: string | null
|
||||||
localDriveCapacityMb: number
|
localDriveCapacityMb: number
|
||||||
remoteDriveCapacityMb: number
|
remoteDriveCapacityMb: number
|
||||||
|
antennaLimit: number
|
||||||
summalyProxy: string | null
|
summalyProxy: string | null
|
||||||
enableEmail: boolean
|
enableEmail: boolean
|
||||||
email: string | null
|
email: string | null
|
||||||
|
|
|
@ -173,6 +173,8 @@ pub struct Model {
|
||||||
pub more_urls: Json,
|
pub more_urls: Json,
|
||||||
#[sea_orm(column_name = "markLocalFilesNsfwByDefault")]
|
#[sea_orm(column_name = "markLocalFilesNsfwByDefault")]
|
||||||
pub mark_local_files_nsfw_by_default: bool,
|
pub mark_local_files_nsfw_by_default: bool,
|
||||||
|
#[sea_orm(column_name = "antennaLimit")]
|
||||||
|
pub antenna_limit: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
|
19
packages/backend/src/migration/1712937600000-antennaLimit.ts
Normal file
19
packages/backend/src/migration/1712937600000-antennaLimit.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import type { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class antennaLimit1712937600000 implements MigrationInterface {
|
||||||
|
async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "meta" ADD "antennaLimit" integer NOT NULL DEFAULT 5`,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`COMMENT ON COLUMN "meta"."antennaLimit" IS 'Antenna Limit'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "meta" DROP COLUMN "antennaLimit"`,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -276,6 +276,12 @@ export class Meta {
|
||||||
})
|
})
|
||||||
public remoteDriveCapacityMb: number;
|
public remoteDriveCapacityMb: number;
|
||||||
|
|
||||||
|
@Column("integer", {
|
||||||
|
default: 5,
|
||||||
|
comment: "Antenna Limit",
|
||||||
|
})
|
||||||
|
public antennaLimit: number;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: 128,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
|
|
|
@ -24,6 +24,11 @@ export const meta = {
|
||||||
optional: false,
|
optional: false,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
},
|
},
|
||||||
|
antennaLimit: {
|
||||||
|
type: "number",
|
||||||
|
optional: false,
|
||||||
|
nullable: false,
|
||||||
|
},
|
||||||
cacheRemoteFiles: {
|
cacheRemoteFiles: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
optional: false,
|
optional: false,
|
||||||
|
@ -487,6 +492,7 @@ export default define(meta, paramDef, async () => {
|
||||||
enableGuestTimeline: instance.enableGuestTimeline,
|
enableGuestTimeline: instance.enableGuestTimeline,
|
||||||
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
|
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
|
||||||
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
|
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
|
||||||
|
antennaLimit: instance.antennaLimit,
|
||||||
emailRequiredForSignup: instance.emailRequiredForSignup,
|
emailRequiredForSignup: instance.emailRequiredForSignup,
|
||||||
enableHcaptcha: instance.enableHcaptcha,
|
enableHcaptcha: instance.enableHcaptcha,
|
||||||
hcaptchaSiteKey: instance.hcaptchaSiteKey,
|
hcaptchaSiteKey: instance.hcaptchaSiteKey,
|
||||||
|
|
|
@ -94,6 +94,7 @@ export const paramDef = {
|
||||||
defaultDarkTheme: { type: "string", nullable: true },
|
defaultDarkTheme: { type: "string", nullable: true },
|
||||||
localDriveCapacityMb: { type: "integer" },
|
localDriveCapacityMb: { type: "integer" },
|
||||||
remoteDriveCapacityMb: { type: "integer" },
|
remoteDriveCapacityMb: { type: "integer" },
|
||||||
|
antennaLimit: { type: "integer" },
|
||||||
cacheRemoteFiles: { type: "boolean" },
|
cacheRemoteFiles: { type: "boolean" },
|
||||||
markLocalFilesNsfwByDefault: { type: "boolean" },
|
markLocalFilesNsfwByDefault: { type: "boolean" },
|
||||||
emailRequiredForSignup: { type: "boolean" },
|
emailRequiredForSignup: { type: "boolean" },
|
||||||
|
@ -327,6 +328,10 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
set.remoteDriveCapacityMb = ps.remoteDriveCapacityMb;
|
set.remoteDriveCapacityMb = ps.remoteDriveCapacityMb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.antennaLimit !== undefined) {
|
||||||
|
set.antennaLimit = ps.antennaLimit;
|
||||||
|
}
|
||||||
|
|
||||||
if (ps.cacheRemoteFiles !== undefined) {
|
if (ps.cacheRemoteFiles !== undefined) {
|
||||||
set.cacheRemoteFiles = ps.cacheRemoteFiles;
|
set.cacheRemoteFiles = ps.cacheRemoteFiles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { genId } from "backend-rs";
|
import { fetchMeta, genId } from "backend-rs";
|
||||||
import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
|
import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { ApiError } from "@/server/api/error.js";
|
||||||
import { publishInternalEvent } from "@/services/stream.js";
|
import { publishInternalEvent } from "@/services/stream.js";
|
||||||
|
@ -109,10 +109,12 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
let userList;
|
let userList;
|
||||||
let userGroupJoining;
|
let userGroupJoining;
|
||||||
|
|
||||||
|
const instance = await fetchMeta(true);
|
||||||
|
|
||||||
const antennas = await Antennas.findBy({
|
const antennas = await Antennas.findBy({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
});
|
});
|
||||||
if (antennas.length > 5 && !user.isAdmin) {
|
if (antennas.length >= instance.antennaLimit) {
|
||||||
throw new ApiError(meta.errors.tooManyAntennas);
|
throw new ApiError(meta.errors.tooManyAntennas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,11 @@ export const meta = {
|
||||||
optional: false,
|
optional: false,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
},
|
},
|
||||||
|
antennaLimit: {
|
||||||
|
type: "number",
|
||||||
|
optional: false,
|
||||||
|
nullable: false,
|
||||||
|
},
|
||||||
cacheRemoteFiles: {
|
cacheRemoteFiles: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
optional: false,
|
optional: false,
|
||||||
|
@ -445,6 +450,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
enableGuestTimeline: instance.enableGuestTimeline,
|
enableGuestTimeline: instance.enableGuestTimeline,
|
||||||
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
|
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
|
||||||
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
|
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
|
||||||
|
antennaLimit: instance.antennaLimit,
|
||||||
emailRequiredForSignup: instance.emailRequiredForSignup,
|
emailRequiredForSignup: instance.emailRequiredForSignup,
|
||||||
enableHcaptcha: instance.enableHcaptcha,
|
enableHcaptcha: instance.enableHcaptcha,
|
||||||
hcaptchaSiteKey: instance.hcaptchaSiteKey,
|
hcaptchaSiteKey: instance.hcaptchaSiteKey,
|
||||||
|
|
|
@ -350,6 +350,19 @@
|
||||||
</FormSplit>
|
</FormSplit>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|
||||||
|
<FormSection>
|
||||||
|
<template #label>{{ i18n.ts.antennas }}</template>
|
||||||
|
<FormInput
|
||||||
|
v-model="antennaLimit"
|
||||||
|
type="number"
|
||||||
|
class="_formBlock"
|
||||||
|
>
|
||||||
|
<template #label>{{
|
||||||
|
i18n.ts.antennaLimit
|
||||||
|
}}</template>
|
||||||
|
</FormInput>
|
||||||
|
</FormSection>
|
||||||
|
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label>ServiceWorker</template>
|
<template #label>ServiceWorker</template>
|
||||||
|
|
||||||
|
@ -502,6 +515,7 @@ const cacheRemoteFiles = ref(false);
|
||||||
const markLocalFilesNsfwByDefault = ref(false);
|
const markLocalFilesNsfwByDefault = ref(false);
|
||||||
const localDriveCapacityMb = ref(0);
|
const localDriveCapacityMb = ref(0);
|
||||||
const remoteDriveCapacityMb = ref(0);
|
const remoteDriveCapacityMb = ref(0);
|
||||||
|
const antennaLimit = ref(0);
|
||||||
const enableRegistration = ref(false);
|
const enableRegistration = ref(false);
|
||||||
const emailRequiredForSignup = ref(false);
|
const emailRequiredForSignup = ref(false);
|
||||||
const enableServiceWorker = ref(false);
|
const enableServiceWorker = ref(false);
|
||||||
|
@ -579,6 +593,7 @@ async function init() {
|
||||||
markLocalFilesNsfwByDefault.value = meta.markLocalFilesNsfwByDefault;
|
markLocalFilesNsfwByDefault.value = meta.markLocalFilesNsfwByDefault;
|
||||||
localDriveCapacityMb.value = meta.driveCapacityPerLocalUserMb;
|
localDriveCapacityMb.value = meta.driveCapacityPerLocalUserMb;
|
||||||
remoteDriveCapacityMb.value = meta.driveCapacityPerRemoteUserMb;
|
remoteDriveCapacityMb.value = meta.driveCapacityPerRemoteUserMb;
|
||||||
|
antennaLimit.value = meta.antennaLimit;
|
||||||
enableRegistration.value = !meta.disableRegistration;
|
enableRegistration.value = !meta.disableRegistration;
|
||||||
emailRequiredForSignup.value = meta.emailRequiredForSignup;
|
emailRequiredForSignup.value = meta.emailRequiredForSignup;
|
||||||
enableServiceWorker.value = meta.enableServiceWorker;
|
enableServiceWorker.value = meta.enableServiceWorker;
|
||||||
|
@ -631,6 +646,7 @@ function save() {
|
||||||
markLocalFilesNsfwByDefault: markLocalFilesNsfwByDefault.value,
|
markLocalFilesNsfwByDefault: markLocalFilesNsfwByDefault.value,
|
||||||
localDriveCapacityMb: localDriveCapacityMb.value,
|
localDriveCapacityMb: localDriveCapacityMb.value,
|
||||||
remoteDriveCapacityMb: remoteDriveCapacityMb.value,
|
remoteDriveCapacityMb: remoteDriveCapacityMb.value,
|
||||||
|
antennaLimit: antennaLimit.value,
|
||||||
disableRegistration: !enableRegistration.value,
|
disableRegistration: !enableRegistration.value,
|
||||||
emailRequiredForSignup: emailRequiredForSignup.value,
|
emailRequiredForSignup: emailRequiredForSignup.value,
|
||||||
enableServiceWorker: enableServiceWorker.value,
|
enableServiceWorker: enableServiceWorker.value,
|
||||||
|
|
|
@ -356,6 +356,7 @@ export type LiteInstanceMetadata = {
|
||||||
disableGlobalTimeline: boolean;
|
disableGlobalTimeline: boolean;
|
||||||
driveCapacityPerLocalUserMb: number;
|
driveCapacityPerLocalUserMb: number;
|
||||||
driveCapacityPerRemoteUserMb: number;
|
driveCapacityPerRemoteUserMb: number;
|
||||||
|
antennaLimit: number;
|
||||||
enableHcaptcha: boolean;
|
enableHcaptcha: boolean;
|
||||||
hcaptchaSiteKey: string | null;
|
hcaptchaSiteKey: string | null;
|
||||||
enableRecaptcha: boolean;
|
enableRecaptcha: boolean;
|
||||||
|
|
Loading…
Reference in a new issue