mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 04:48:53 +00:00
chore: rename fundamentals to base (#9119)
This commit is contained in:
@@ -2,7 +2,7 @@ import {
|
||||
defineRuntimeConfig,
|
||||
defineStartupConfig,
|
||||
ModuleConfig,
|
||||
} from '../../fundamentals/config';
|
||||
} from '../../base/config';
|
||||
import { CaptchaConfig } from './types';
|
||||
|
||||
declare module '../config' {
|
||||
@@ -16,7 +16,7 @@ declare module '../config' {
|
||||
}
|
||||
}
|
||||
|
||||
declare module '../../fundamentals/guard' {
|
||||
declare module '../../base/guard' {
|
||||
interface RegisterGuardName {
|
||||
captcha: 'captcha';
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
|
||||
import { Throttle } from '../../base';
|
||||
import { Public } from '../../core/auth';
|
||||
import { Throttle } from '../../fundamentals';
|
||||
import { CaptchaService } from './service';
|
||||
|
||||
@Throttle('strict')
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Config,
|
||||
getRequestResponseFromContext,
|
||||
GuardProvider,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { CaptchaService } from './service';
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -6,12 +6,12 @@ import type { Request } from 'express';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { TokenService, TokenType } from '../../core/auth/token';
|
||||
import {
|
||||
CaptchaVerificationFailed,
|
||||
Config,
|
||||
verifyChallengeResponse,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { TokenService, TokenType } from '../../core/auth/token';
|
||||
import { CaptchaConfig } from './types';
|
||||
|
||||
const validator = z
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ModuleStartupConfigDescriptions } from '../fundamentals/config/types';
|
||||
import { ModuleStartupConfigDescriptions } from '../base/config/types';
|
||||
|
||||
export interface PluginsConfig {}
|
||||
export type AvailablePlugins = keyof PluginsConfig;
|
||||
|
||||
declare module '../fundamentals/config' {
|
||||
declare module '../base/config' {
|
||||
interface AppConfig {
|
||||
plugins: PluginsConfig;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ClientOptions as OpenAIClientOptions } from 'openai';
|
||||
|
||||
import { defineStartupConfig, ModuleConfig } from '../../fundamentals/config';
|
||||
import { StorageConfig } from '../../fundamentals/storage/config';
|
||||
import { defineStartupConfig, ModuleConfig } from '../../base/config';
|
||||
import { StorageConfig } from '../../base/storage/config';
|
||||
import type { FalConfig } from './providers/fal';
|
||||
|
||||
export interface CopilotStartupConfigurations {
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
toArray,
|
||||
} from 'rxjs';
|
||||
|
||||
import { CurrentUser, Public } from '../../core/auth';
|
||||
import {
|
||||
BlobNotFound,
|
||||
CallMetric,
|
||||
@@ -38,7 +37,8 @@ import {
|
||||
metrics,
|
||||
NoCopilotProviderAvailable,
|
||||
UnsplashIsNotConfigured,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { CurrentUser, Public } from '../../core/auth';
|
||||
import { CopilotProviderService } from './providers';
|
||||
import { ChatSession, ChatSessionService } from './session';
|
||||
import { CopilotStorage } from './storage';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { SessionCache } from '../../fundamentals';
|
||||
import { SessionCache } from '../../base';
|
||||
import { SubmittedMessage, SubmittedMessageSchema } from './types';
|
||||
|
||||
const CHAT_MESSAGE_KEY = 'chat-message';
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
CopilotProviderSideError,
|
||||
metrics,
|
||||
UserFriendlyError,
|
||||
} from '../../../fundamentals';
|
||||
} from '../../../base';
|
||||
import {
|
||||
CopilotCapability,
|
||||
CopilotChatOptions,
|
||||
|
||||
@@ -2,7 +2,7 @@ import assert from 'node:assert';
|
||||
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { AFFiNEConfig, Config } from '../../../fundamentals';
|
||||
import { AFFiNEConfig, Config } from '../../../base';
|
||||
import { CopilotStartupConfigurations } from '../config';
|
||||
import {
|
||||
CapabilityToCopilotProvider,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
CopilotProviderSideError,
|
||||
metrics,
|
||||
UserFriendlyError,
|
||||
} from '../../../fundamentals';
|
||||
} from '../../../base';
|
||||
import {
|
||||
ChatMessageRole,
|
||||
CopilotCapability,
|
||||
|
||||
@@ -19,10 +19,6 @@ import { AiPromptRole } from '@prisma/client';
|
||||
import { GraphQLJSON, SafeIntResolver } from 'graphql-scalars';
|
||||
import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs';
|
||||
|
||||
import { CurrentUser } from '../../core/auth';
|
||||
import { Admin } from '../../core/common';
|
||||
import { PermissionService } from '../../core/permission';
|
||||
import { UserType } from '../../core/user';
|
||||
import {
|
||||
CallMetric,
|
||||
CopilotFailedToCreateMessage,
|
||||
@@ -30,7 +26,11 @@ import {
|
||||
RequestMutex,
|
||||
Throttle,
|
||||
TooManyRequest,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { CurrentUser } from '../../core/auth';
|
||||
import { Admin } from '../../core/common';
|
||||
import { PermissionService } from '../../core/permission';
|
||||
import { UserType } from '../../core/user';
|
||||
import { PromptService } from './prompt';
|
||||
import { ChatSessionService } from './session';
|
||||
import { CopilotStorage } from './storage';
|
||||
|
||||
@@ -3,8 +3,6 @@ import { randomUUID } from 'node:crypto';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { AiPromptRole, PrismaClient } from '@prisma/client';
|
||||
|
||||
import { FeatureManagementService } from '../../core/features';
|
||||
import { QuotaService } from '../../core/quota';
|
||||
import {
|
||||
CopilotActionTaken,
|
||||
CopilotMessageNotFound,
|
||||
@@ -12,7 +10,9 @@ import {
|
||||
CopilotQuotaExceeded,
|
||||
CopilotSessionDeleted,
|
||||
CopilotSessionNotFound,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { FeatureManagementService } from '../../core/features';
|
||||
import { QuotaService } from '../../core/quota';
|
||||
import { ChatMessageCache } from './message';
|
||||
import { PromptService } from './prompt';
|
||||
import {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { createHash } from 'node:crypto';
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { QuotaManagementService } from '../../core/quota';
|
||||
import {
|
||||
type BlobInputType,
|
||||
BlobQuotaExceeded,
|
||||
@@ -12,7 +11,8 @@ import {
|
||||
type StorageProvider,
|
||||
StorageProviderFactory,
|
||||
URLHelper,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { QuotaManagementService } from '../../core/quota';
|
||||
|
||||
@Injectable()
|
||||
export class CopilotStorage {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineStartupConfig, ModuleConfig } from '../../fundamentals/config';
|
||||
import { defineStartupConfig, ModuleConfig } from '../../base/config';
|
||||
|
||||
export interface GCloudConfig {
|
||||
enabled: boolean;
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
} from '@opentelemetry/sdk-metrics';
|
||||
import { SpanExporter } from '@opentelemetry/sdk-trace-node';
|
||||
|
||||
import { OptionalModule } from '../../fundamentals';
|
||||
import { OpentelemetryFactory } from '../../fundamentals/metrics';
|
||||
import { OptionalModule } from '../../base';
|
||||
import { OpentelemetryFactory } from '../../base/metrics';
|
||||
|
||||
export class GCloudOpentelemetryFactory extends OpentelemetryFactory {
|
||||
override getResource(): Resource {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineStartupConfig, ModuleConfig } from '../../fundamentals/config';
|
||||
import { defineStartupConfig, ModuleConfig } from '../../base/config';
|
||||
|
||||
export interface OAuthProviderConfig {
|
||||
clientId: string;
|
||||
|
||||
@@ -10,15 +10,15 @@ import {
|
||||
import { ConnectedAccount, PrismaClient } from '@prisma/client';
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import { AuthService, Public } from '../../core/auth';
|
||||
import { UserService } from '../../core/user';
|
||||
import {
|
||||
InvalidOauthCallbackState,
|
||||
MissingOauthQueryParameter,
|
||||
OauthAccountAlreadyConnected,
|
||||
OauthStateExpired,
|
||||
UnknownOauthProvider,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { AuthService, Public } from '../../core/auth';
|
||||
import { UserService } from '../../core/user';
|
||||
import { OAuthProviderName } from './config';
|
||||
import { OAuthAccount, Tokens } from './providers/def';
|
||||
import { OAuthProviderFactory } from './register';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { Config, URLHelper } from '../../../fundamentals';
|
||||
import { Config, URLHelper } from '../../../base';
|
||||
import { OAuthProviderName } from '../config';
|
||||
import { AutoRegisteredOAuthProvider } from '../register';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { Config, URLHelper } from '../../../fundamentals';
|
||||
import { Config, URLHelper } from '../../../base';
|
||||
import { OAuthProviderName } from '../config';
|
||||
import { AutoRegisteredOAuthProvider } from '../register';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Config, URLHelper } from '../../../fundamentals';
|
||||
import { Config, URLHelper } from '../../../base';
|
||||
import {
|
||||
OAuthOIDCProviderConfig,
|
||||
OAuthProviderName,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
||||
|
||||
import { Config } from '../../fundamentals';
|
||||
import { Config } from '../../base';
|
||||
import { OAuthProviderName } from './config';
|
||||
import { OAuthProvider } from './providers/def';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { SessionCache } from '../../fundamentals';
|
||||
import { SessionCache } from '../../base';
|
||||
import { OAuthProviderName } from './config';
|
||||
import { OAuthProviderFactory } from './register';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
defineRuntimeConfig,
|
||||
defineStartupConfig,
|
||||
ModuleConfig,
|
||||
} from '../../fundamentals/config';
|
||||
} from '../../base/config';
|
||||
|
||||
export interface PaymentStartupConfig {
|
||||
stripe?: {
|
||||
|
||||
@@ -6,8 +6,8 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import type { Request } from 'express';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
import { Config, InternalServerError } from '../../base';
|
||||
import { Public } from '../../core/auth';
|
||||
import { Config, InternalServerError } from '../../fundamentals';
|
||||
|
||||
@Controller('/api/stripe')
|
||||
export class StripeWebhookController {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Cron, CronExpression } from '@nestjs/schedule';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
import { EventEmitter, type EventPayload } from '../../fundamentals';
|
||||
import { EventEmitter, type EventPayload } from '../../base';
|
||||
import {
|
||||
SubscriptionPlan,
|
||||
SubscriptionRecurring,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { PrismaClient, UserStripeCustomer } from '@prisma/client';
|
||||
import Stripe from 'stripe';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { UserNotFound } from '../../../fundamentals';
|
||||
import { UserNotFound } from '../../../base';
|
||||
import { ScheduleManager } from '../schedule';
|
||||
import {
|
||||
encodeLookupKey,
|
||||
|
||||
@@ -4,10 +4,6 @@ import { omit, pick } from 'lodash-es';
|
||||
import Stripe from 'stripe';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
EarlyAccessType,
|
||||
FeatureManagementService,
|
||||
} from '../../../core/features';
|
||||
import {
|
||||
Config,
|
||||
EventEmitter,
|
||||
@@ -16,7 +12,11 @@ import {
|
||||
SubscriptionAlreadyExists,
|
||||
SubscriptionPlanNotFound,
|
||||
URLHelper,
|
||||
} from '../../../fundamentals';
|
||||
} from '../../../base';
|
||||
import {
|
||||
EarlyAccessType,
|
||||
FeatureManagementService,
|
||||
} from '../../../core/features';
|
||||
import {
|
||||
CouponType,
|
||||
KnownStripeInvoice,
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
SubscriptionAlreadyExists,
|
||||
SubscriptionPlanNotFound,
|
||||
URLHelper,
|
||||
} from '../../../fundamentals';
|
||||
} from '../../../base';
|
||||
import {
|
||||
KnownStripeInvoice,
|
||||
KnownStripePrice,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
|
||||
import type { EventPayload } from '../../base';
|
||||
import { PermissionService } from '../../core/permission';
|
||||
import { QuotaManagementService, QuotaType } from '../../core/quota';
|
||||
import type { EventPayload } from '../../fundamentals';
|
||||
|
||||
@Injectable()
|
||||
export class TeamQuotaOverride {
|
||||
|
||||
@@ -18,15 +18,15 @@ import { GraphQLJSONObject } from 'graphql-scalars';
|
||||
import { groupBy } from 'lodash-es';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { CurrentUser, Public } from '../../core/auth';
|
||||
import { Permission, PermissionService } from '../../core/permission';
|
||||
import { UserType } from '../../core/user';
|
||||
import { WorkspaceType } from '../../core/workspaces';
|
||||
import {
|
||||
AccessDenied,
|
||||
FailedToCheckout,
|
||||
WorkspaceIdRequiredToUpdateTeamSubscription,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { CurrentUser, Public } from '../../core/auth';
|
||||
import { Permission, PermissionService } from '../../core/permission';
|
||||
import { UserType } from '../../core/user';
|
||||
import { WorkspaceType } from '../../core/workspaces';
|
||||
import { Invoice, Subscription, WorkspaceSubscriptionManager } from './manager';
|
||||
import { CheckoutParams, SubscriptionService } from './service';
|
||||
import {
|
||||
|
||||
@@ -4,9 +4,6 @@ import { PrismaClient } from '@prisma/client';
|
||||
import Stripe from 'stripe';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { CurrentUser } from '../../core/auth';
|
||||
import { FeatureManagementService } from '../../core/features';
|
||||
import { UserService } from '../../core/user';
|
||||
import {
|
||||
ActionForbidden,
|
||||
CantUpdateOnetimePaymentSubscription,
|
||||
@@ -25,7 +22,10 @@ import {
|
||||
SubscriptionPlanNotFound,
|
||||
UnsupportedSubscriptionPlan,
|
||||
UserNotFound,
|
||||
} from '../../fundamentals';
|
||||
} from '../../base';
|
||||
import { CurrentUser } from '../../core/auth';
|
||||
import { FeatureManagementService } from '../../core/features';
|
||||
import { UserService } from '../../core/user';
|
||||
import {
|
||||
CheckoutParams,
|
||||
Invoice,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FactoryProvider } from '@nestjs/common';
|
||||
import { omit } from 'lodash-es';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
import { Config } from '../../fundamentals';
|
||||
import { Config } from '../../base';
|
||||
|
||||
export const StripeProvider: FactoryProvider = {
|
||||
provide: Stripe,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { User, Workspace } from '@prisma/client';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
import type { Payload } from '../../fundamentals/event/def';
|
||||
import type { Payload } from '../../base/event/def';
|
||||
|
||||
export enum SubscriptionRecurring {
|
||||
Monthly = 'monthly',
|
||||
@@ -49,7 +49,7 @@ export enum CouponType {
|
||||
ProEarlyAccessAIOneYearFree = 'ai_pro_ea_one_year_free',
|
||||
}
|
||||
|
||||
declare module '../../fundamentals/event/def' {
|
||||
declare module '../../base/event/def' {
|
||||
interface UserEvents {
|
||||
subscription: {
|
||||
activated: Payload<{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Redis } from 'ioredis';
|
||||
|
||||
import type { Cache, CacheSetOptions } from '../../fundamentals/cache/def';
|
||||
import type { Cache, CacheSetOptions } from '../../base/cache/def';
|
||||
|
||||
export class RedisCache implements Cache {
|
||||
constructor(private readonly redis: Redis) {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RedisOptions } from 'ioredis';
|
||||
|
||||
import { defineStartupConfig, ModuleConfig } from '../../fundamentals/config';
|
||||
import { defineStartupConfig, ModuleConfig } from '../../base/config';
|
||||
|
||||
declare module '../config' {
|
||||
interface PluginsConfig {
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Global, Provider, Type } from '@nestjs/common';
|
||||
import { Redis } from 'ioredis';
|
||||
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
|
||||
|
||||
import { Cache, Locker, SessionCache } from '../../fundamentals';
|
||||
import { ThrottlerStorage } from '../../fundamentals/throttler';
|
||||
import { SocketIoAdapterImpl } from '../../fundamentals/websocket';
|
||||
import { Cache, Locker, SessionCache } from '../../base';
|
||||
import { ThrottlerStorage } from '../../base/throttler';
|
||||
import { SocketIoAdapterImpl } from '../../base/websocket';
|
||||
import { Plugin } from '../registry';
|
||||
import { RedisCache } from './cache';
|
||||
import { CacheRedis, SessionRedis, SocketIoRedis } from './instances';
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Redis as IORedis, RedisOptions } from 'ioredis';
|
||||
|
||||
import { Config } from '../../fundamentals/config';
|
||||
import { Config } from '../../base/config';
|
||||
|
||||
class Redis extends IORedis implements OnModuleDestroy, OnModuleInit {
|
||||
logger = new Logger(Redis.name);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Command } from 'ioredis';
|
||||
|
||||
import { ILocker, Lock } from '../../fundamentals';
|
||||
import { ILocker, Lock } from '../../base';
|
||||
import { SessionRedis } from './instances';
|
||||
|
||||
// === atomic mutex lock ===
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createAdapter } from '@socket.io/redis-adapter';
|
||||
import { Redis } from 'ioredis';
|
||||
import { Server, ServerOptions } from 'socket.io';
|
||||
|
||||
import { SocketIoAdapter } from '../../fundamentals/websocket';
|
||||
import { SocketIoAdapter } from '../../base/websocket';
|
||||
|
||||
export function createSockerIoAdapterImpl(
|
||||
redis: Redis
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { get, merge, omit, set } from 'lodash-es';
|
||||
|
||||
import { OptionalModule, OptionalModuleMetadata } from '../fundamentals/nestjs';
|
||||
import { OptionalModule, OptionalModuleMetadata } from '../base/nestjs';
|
||||
import { AvailablePlugins } from './config';
|
||||
|
||||
export const REGISTERED_PLUGINS = new Map<AvailablePlugins, AFFiNEModule>();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { S3ClientConfig, S3ClientConfigType } from '@aws-sdk/client-s3';
|
||||
|
||||
import { defineStartupConfig, ModuleConfig } from '../../fundamentals/config';
|
||||
import { defineStartupConfig, ModuleConfig } from '../../base/config';
|
||||
|
||||
type WARNING = '__YOU_SHOULD_NOT_MANUALLY_CONFIGURATE_THIS_TYPE__';
|
||||
declare module '../../fundamentals/storage/config' {
|
||||
declare module '../../base/storage/config' {
|
||||
interface StorageProvidersConfig {
|
||||
// the type here is only existing for extends [StorageProviderType] with better type inference and checking.
|
||||
'cloudflare-r2'?: WARNING;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import './config';
|
||||
|
||||
import { registerStorageProvider } from '../../fundamentals/storage';
|
||||
import { registerStorageProvider } from '../../base/storage';
|
||||
import { Plugin } from '../registry';
|
||||
import { R2StorageProvider } from './providers/r2';
|
||||
import { S3StorageProvider } from './providers/s3';
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
PutObjectMetadata,
|
||||
StorageProvider,
|
||||
toBuffer,
|
||||
} from '../../../fundamentals/storage';
|
||||
} from '../../../base/storage';
|
||||
import type { S3StorageConfig } from '../config';
|
||||
|
||||
export class S3StorageProvider implements StorageProvider {
|
||||
|
||||
Reference in New Issue
Block a user