removing the need of suplementing provider links in config
This commit is contained in:
@@ -38,6 +38,7 @@ import notificationRoutes from './routes/notifications';
|
|||||||
import shareRoutes from './routes/share';
|
import shareRoutes from './routes/share';
|
||||||
import { mcpHandler } from './mcp';
|
import { mcpHandler } from './mcp';
|
||||||
import { Addon } from './types';
|
import { Addon } from './types';
|
||||||
|
import { getPhotoProviderConfig } from './services/memories/helpersService';
|
||||||
|
|
||||||
export function createApp(): express.Application {
|
export function createApp(): express.Application {
|
||||||
const app = express();
|
const app = express();
|
||||||
@@ -194,11 +195,11 @@ export function createApp(): express.Application {
|
|||||||
app.get('/api/addons', authenticate, (_req: Request, res: Response) => {
|
app.get('/api/addons', authenticate, (_req: Request, res: Response) => {
|
||||||
const addons = db.prepare('SELECT id, name, type, icon, enabled FROM addons WHERE enabled = 1 ORDER BY sort_order').all() as Pick<Addon, 'id' | 'name' | 'type' | 'icon' | 'enabled'>[];
|
const addons = db.prepare('SELECT id, name, type, icon, enabled FROM addons WHERE enabled = 1 ORDER BY sort_order').all() as Pick<Addon, 'id' | 'name' | 'type' | 'icon' | 'enabled'>[];
|
||||||
const providers = db.prepare(`
|
const providers = db.prepare(`
|
||||||
SELECT id, name, icon, enabled, config, sort_order
|
SELECT id, name, icon, enabled, sort_order
|
||||||
FROM photo_providers
|
FROM photo_providers
|
||||||
WHERE enabled = 1
|
WHERE enabled = 1
|
||||||
ORDER BY sort_order, id
|
ORDER BY sort_order, id
|
||||||
`).all() as Array<{ id: string; name: string; icon: string; enabled: number; config: string; sort_order: number }>;
|
`).all() as Array<{ id: string; name: string; icon: string; enabled: number; sort_order: number }>;
|
||||||
const fields = db.prepare(`
|
const fields = db.prepare(`
|
||||||
SELECT provider_id, field_key, label, input_type, placeholder, required, secret, settings_key, payload_key, sort_order
|
SELECT provider_id, field_key, label, input_type, placeholder, required, secret, settings_key, payload_key, sort_order
|
||||||
FROM photo_provider_fields
|
FROM photo_provider_fields
|
||||||
@@ -232,7 +233,7 @@ export function createApp(): express.Application {
|
|||||||
type: 'photo_provider',
|
type: 'photo_provider',
|
||||||
icon: p.icon,
|
icon: p.icon,
|
||||||
enabled: !!p.enabled,
|
enabled: !!p.enabled,
|
||||||
config: JSON.parse(p.config || '{}'),
|
config: getPhotoProviderConfig(p.id),
|
||||||
fields: (fieldsByProvider.get(p.id) || []).map(f => ({
|
fields: (fieldsByProvider.get(p.id) || []).map(f => ({
|
||||||
key: f.field_key,
|
key: f.field_key,
|
||||||
label: f.label,
|
label: f.label,
|
||||||
|
|||||||
@@ -643,14 +643,13 @@ function runMigrations(db: Database.Database): void {
|
|||||||
// Seed Synology Photos provider and fields in existing databases
|
// Seed Synology Photos provider and fields in existing databases
|
||||||
try {
|
try {
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
INSERT INTO photo_providers (id, name, description, icon, enabled, config, sort_order)
|
INSERT INTO photo_providers (id, name, description, icon, enabled, sort_order)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
ON CONFLICT(id) DO UPDATE SET
|
ON CONFLICT(id) DO UPDATE SET
|
||||||
name = excluded.name,
|
name = excluded.name,
|
||||||
description = excluded.description,
|
description = excluded.description,
|
||||||
icon = excluded.icon,
|
icon = excluded.icon,
|
||||||
enabled = excluded.enabled,
|
enabled = excluded.enabled,
|
||||||
config = excluded.config,
|
|
||||||
sort_order = excluded.sort_order
|
sort_order = excluded.sort_order
|
||||||
`).run(
|
`).run(
|
||||||
'synologyphotos',
|
'synologyphotos',
|
||||||
@@ -658,12 +657,6 @@ function runMigrations(db: Database.Database): void {
|
|||||||
'Synology Photos integration with separate account settings',
|
'Synology Photos integration with separate account settings',
|
||||||
'Image',
|
'Image',
|
||||||
0,
|
0,
|
||||||
JSON.stringify({
|
|
||||||
settings_get: '/integrations/synologyphotos/settings',
|
|
||||||
settings_put: '/integrations/synologyphotos/settings',
|
|
||||||
status_get: '/integrations/synologyphotos/status',
|
|
||||||
test_post: '/integrations/synologyphotos/test',
|
|
||||||
}),
|
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@@ -691,6 +684,14 @@ function runMigrations(db: Database.Database): void {
|
|||||||
if (!err.message?.includes('no such table')) throw err;
|
if (!err.message?.includes('no such table')) throw err;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
() => {
|
||||||
|
// Remove the stored config column from photo_providers now that it is generated from provider id.
|
||||||
|
const columns = db.prepare("PRAGMA table_info('photo_providers')").all() as Array<{ name: string }>;
|
||||||
|
const names = new Set(columns.map(c => c.name));
|
||||||
|
if (!names.has('config')) return;
|
||||||
|
|
||||||
|
db.exec('ALTER TABLE photo_providers DROP COLUMN config');
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (currentVersion < migrations.length) {
|
if (currentVersion < migrations.length) {
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ function createTables(db: Database.Database): void {
|
|||||||
description TEXT,
|
description TEXT,
|
||||||
icon TEXT DEFAULT 'Image',
|
icon TEXT DEFAULT 'Image',
|
||||||
enabled INTEGER DEFAULT 0,
|
enabled INTEGER DEFAULT 0,
|
||||||
config TEXT DEFAULT '{}',
|
|
||||||
sort_order INTEGER DEFAULT 0
|
sort_order INTEGER DEFAULT 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -101,12 +101,6 @@ function seedAddons(db: Database.Database): void {
|
|||||||
icon: 'Image',
|
icon: 'Image',
|
||||||
enabled: 0,
|
enabled: 0,
|
||||||
sort_order: 0,
|
sort_order: 0,
|
||||||
config: JSON.stringify({
|
|
||||||
settings_get: '/integrations/immich/settings',
|
|
||||||
settings_put: '/integrations/immich/settings',
|
|
||||||
status_get: '/integrations/immich/status',
|
|
||||||
test_post: '/integrations/immich/test',
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'synologyphotos',
|
id: 'synologyphotos',
|
||||||
@@ -115,16 +109,10 @@ function seedAddons(db: Database.Database): void {
|
|||||||
icon: 'Image',
|
icon: 'Image',
|
||||||
enabled: 0,
|
enabled: 0,
|
||||||
sort_order: 1,
|
sort_order: 1,
|
||||||
config: JSON.stringify({
|
|
||||||
settings_get: '/integrations/synologyphotos/settings',
|
|
||||||
settings_put: '/integrations/synologyphotos/settings',
|
|
||||||
status_get: '/integrations/synologyphotos/status',
|
|
||||||
test_post: '/integrations/synologyphotos/test',
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const insertProvider = db.prepare('INSERT OR IGNORE INTO photo_providers (id, name, description, icon, enabled, config, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?)');
|
const insertProvider = db.prepare('INSERT OR IGNORE INTO photo_providers (id, name, description, icon, enabled, sort_order) VALUES (?, ?, ?, ?, ?, ?)');
|
||||||
for (const p of providerRows) insertProvider.run(p.id, p.name, p.description, p.icon, p.enabled, p.config, p.sort_order);
|
for (const p of providerRows) insertProvider.run(p.id, p.name, p.description, p.icon, p.enabled, p.sort_order);
|
||||||
|
|
||||||
const providerFields = [
|
const providerFields = [
|
||||||
{ provider_id: 'immich', field_key: 'immich_url', label: 'Immich URL', input_type: 'url', placeholder: 'https://immich.example.com', required: 1, secret: 0, settings_key: 'immich_url', payload_key: 'immich_url', sort_order: 0 },
|
{ provider_id: 'immich', field_key: 'immich_url', label: 'Immich URL', input_type: 'url', placeholder: 'https://immich.example.com', required: 1, secret: 0, settings_key: 'immich_url', payload_key: 'immich_url', sort_order: 0 },
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { maybe_encrypt_api_key, decrypt_api_key } from './apiKeyCrypto';
|
|||||||
import { getAllPermissions, savePermissions as savePerms, PERMISSION_ACTIONS } from './permissions';
|
import { getAllPermissions, savePermissions as savePerms, PERMISSION_ACTIONS } from './permissions';
|
||||||
import { revokeUserSessions } from '../mcp';
|
import { revokeUserSessions } from '../mcp';
|
||||||
import { validatePassword } from './passwordPolicy';
|
import { validatePassword } from './passwordPolicy';
|
||||||
|
import { getPhotoProviderConfig } from './memories/helpersService';
|
||||||
|
|
||||||
// ── Helpers ────────────────────────────────────────────────────────────────
|
// ── Helpers ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -466,10 +467,10 @@ export function deleteTemplateItem(itemId: string) {
|
|||||||
export function listAddons() {
|
export function listAddons() {
|
||||||
const addons = db.prepare('SELECT * FROM addons ORDER BY sort_order, id').all() as Addon[];
|
const addons = db.prepare('SELECT * FROM addons ORDER BY sort_order, id').all() as Addon[];
|
||||||
const providers = db.prepare(`
|
const providers = db.prepare(`
|
||||||
SELECT id, name, description, icon, enabled, config, sort_order
|
SELECT id, name, description, icon, enabled, sort_order
|
||||||
FROM photo_providers
|
FROM photo_providers
|
||||||
ORDER BY sort_order, id
|
ORDER BY sort_order, id
|
||||||
`).all() as Array<{ id: string; name: string; description?: string | null; icon: string; enabled: number; config: string; sort_order: number }>;
|
`).all() as Array<{ id: string; name: string; description?: string | null; icon: string; enabled: number; sort_order: number }>;
|
||||||
const fields = db.prepare(`
|
const fields = db.prepare(`
|
||||||
SELECT provider_id, field_key, label, input_type, placeholder, required, secret, settings_key, payload_key, sort_order
|
SELECT provider_id, field_key, label, input_type, placeholder, required, secret, settings_key, payload_key, sort_order
|
||||||
FROM photo_provider_fields
|
FROM photo_provider_fields
|
||||||
@@ -502,7 +503,7 @@ export function listAddons() {
|
|||||||
type: 'photo_provider',
|
type: 'photo_provider',
|
||||||
icon: p.icon,
|
icon: p.icon,
|
||||||
enabled: !!p.enabled,
|
enabled: !!p.enabled,
|
||||||
config: JSON.parse(p.config || '{}'),
|
config: getPhotoProviderConfig(p.id),
|
||||||
fields: (fieldsByProvider.get(p.id) || []).map(f => ({
|
fields: (fieldsByProvider.get(p.id) || []).map(f => ({
|
||||||
key: f.field_key,
|
key: f.field_key,
|
||||||
label: f.label,
|
label: f.label,
|
||||||
@@ -521,7 +522,7 @@ export function listAddons() {
|
|||||||
|
|
||||||
export function updateAddon(id: string, data: { enabled?: boolean; config?: Record<string, unknown> }) {
|
export function updateAddon(id: string, data: { enabled?: boolean; config?: Record<string, unknown> }) {
|
||||||
const addon = db.prepare('SELECT * FROM addons WHERE id = ?').get(id) as Addon | undefined;
|
const addon = db.prepare('SELECT * FROM addons WHERE id = ?').get(id) as Addon | undefined;
|
||||||
const provider = db.prepare('SELECT * FROM photo_providers WHERE id = ?').get(id) as { id: string; name: string; description?: string | null; icon: string; enabled: number; config: string; sort_order: number } | undefined;
|
const provider = db.prepare('SELECT * FROM photo_providers WHERE id = ?').get(id) as { id: string; name: string; description?: string | null; icon: string; enabled: number; sort_order: number } | undefined;
|
||||||
if (!addon && !provider) return { error: 'Addon not found', status: 404 };
|
if (!addon && !provider) return { error: 'Addon not found', status: 404 };
|
||||||
|
|
||||||
if (addon) {
|
if (addon) {
|
||||||
@@ -529,11 +530,10 @@ export function updateAddon(id: string, data: { enabled?: boolean; config?: Reco
|
|||||||
if (data.config !== undefined) db.prepare('UPDATE addons SET config = ? WHERE id = ?').run(JSON.stringify(data.config), id);
|
if (data.config !== undefined) db.prepare('UPDATE addons SET config = ? WHERE id = ?').run(JSON.stringify(data.config), id);
|
||||||
} else {
|
} else {
|
||||||
if (data.enabled !== undefined) db.prepare('UPDATE photo_providers SET enabled = ? WHERE id = ?').run(data.enabled ? 1 : 0, id);
|
if (data.enabled !== undefined) db.prepare('UPDATE photo_providers SET enabled = ? WHERE id = ?').run(data.enabled ? 1 : 0, id);
|
||||||
if (data.config !== undefined) db.prepare('UPDATE photo_providers SET config = ? WHERE id = ?').run(JSON.stringify(data.config), id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedAddon = db.prepare('SELECT * FROM addons WHERE id = ?').get(id) as Addon | undefined;
|
const updatedAddon = db.prepare('SELECT * FROM addons WHERE id = ?').get(id) as Addon | undefined;
|
||||||
const updatedProvider = db.prepare('SELECT * FROM photo_providers WHERE id = ?').get(id) as { id: string; name: string; description?: string | null; icon: string; enabled: number; config: string; sort_order: number } | undefined;
|
const updatedProvider = db.prepare('SELECT * FROM photo_providers WHERE id = ?').get(id) as { id: string; name: string; description?: string | null; icon: string; enabled: number; sort_order: number } | undefined;
|
||||||
const updated = updatedAddon
|
const updated = updatedAddon
|
||||||
? { ...updatedAddon, enabled: !!updatedAddon.enabled, config: JSON.parse(updatedAddon.config || '{}') }
|
? { ...updatedAddon, enabled: !!updatedAddon.enabled, config: JSON.parse(updatedAddon.config || '{}') }
|
||||||
: updatedProvider
|
: updatedProvider
|
||||||
@@ -544,7 +544,7 @@ export function updateAddon(id: string, data: { enabled?: boolean; config?: Reco
|
|||||||
type: 'photo_provider',
|
type: 'photo_provider',
|
||||||
icon: updatedProvider.icon,
|
icon: updatedProvider.icon,
|
||||||
enabled: !!updatedProvider.enabled,
|
enabled: !!updatedProvider.enabled,
|
||||||
config: JSON.parse(updatedProvider.config || '{}'),
|
config: getPhotoProviderConfig(updatedProvider.id),
|
||||||
sort_order: updatedProvider.sort_order,
|
sort_order: updatedProvider.sort_order,
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
@@ -32,6 +32,25 @@ export type Selection = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//for loading routes to settings page, and validating which services user has connected
|
||||||
|
type PhotoProviderConfig = {
|
||||||
|
settings_get: string;
|
||||||
|
settings_put: string;
|
||||||
|
status_get: string;
|
||||||
|
test_post: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export function getPhotoProviderConfig(providerId: string): PhotoProviderConfig {
|
||||||
|
const prefix = `/integrations/memories/${providerId}`;
|
||||||
|
return {
|
||||||
|
settings_get: `${prefix}/settings`,
|
||||||
|
settings_put: `${prefix}/settings`,
|
||||||
|
status_get: `${prefix}/status`,
|
||||||
|
test_post: `${prefix}/test`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
//access check helper
|
//access check helper
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user