fix(plugins): per-tenant plugin store flag and harden broken schema APIs

Store enablement is now a tenant settings row instead of a global runtime switch, and expiring/requests endpoints degrade to empty lists when store tables are missing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-07 19:51:11 +03:30
co-authored by Cursor
parent 1f776cf6e2
commit b3112cf032
9 changed files with 301 additions and 136 deletions
+17 -6
View File
@@ -3,7 +3,7 @@ import { iranDaysUntil } from '../common/iran-time.util';
import { PrismaService } from '../prisma/prisma.service';
import { applyKhanegiNavSample } from './khanegi-nav-sample';
import { rewriteLegacyUploadUrl } from '../uploads/uploads.util';
import { RuntimeSettingsService } from '../notifications/runtime-settings.service';
import { PLUGIN_STORE_SETTING_KEY } from '../program-settings/runtime-setting-keys';
type UiSetting = { key: string; value: string };
@@ -25,10 +25,7 @@ type SubscriptionAlerts = {
@Injectable()
export class GetUserService {
constructor(
private readonly prisma: PrismaService,
private readonly runtime: RuntimeSettingsService,
) {}
constructor(private readonly prisma: PrismaService) {}
async resolveByHost(hostHeader?: string, domainQuery?: string) {
const host = this.normalizeHost(domainQuery || hostHeader || '');
@@ -116,7 +113,9 @@ export class GetUserService {
ui_settings: uiSettings.length ? uiSettings : undefined,
/** Admin expiry modals — near/expired server, plugin, support */
subscription_alerts,
plugin_store_enabled: isKhanegi ? this.runtime.getPluginStoreEnabled() : false,
plugin_store_enabled: isKhanegi
? await this.isPluginStoreEnabled(tenant.id)
: false,
};
return {
@@ -125,6 +124,18 @@ export class GetUserService {
};
}
private async isPluginStoreEnabled(tenantId: string): Promise<boolean> {
try {
const row = await this.prisma.setting.findUnique({
where: { tenantId_key: { tenantId, key: PLUGIN_STORE_SETTING_KEY } },
select: { value: true },
});
return row?.value === 'true';
} catch {
return false;
}
}
private async buildSubscriptionAlerts(tenantId: string): Promise<SubscriptionAlerts> {
const [servers, plugins, supports] = await Promise.all([
this.prisma.serverAccount.findMany({