feat(apps): Add Apps subsystem: App and AppConnection models, managers, typed request handlers, web UI routes and documentation
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import type { Reception } from './classes.reception.js';
|
||||
import { App } from './classes.app.js';
|
||||
|
||||
export class AppManager {
|
||||
public receptionRef: Reception;
|
||||
public get db() {
|
||||
return this.receptionRef.db.smartdataDb;
|
||||
}
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
public CApp = plugins.smartdata.setDefaultManagerForDoc(this, App);
|
||||
|
||||
constructor(receptionRefArg: Reception) {
|
||||
this.receptionRef = receptionRefArg;
|
||||
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
|
||||
// Handler: Get all global apps
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_GetGlobalApps>(
|
||||
'getGlobalApps',
|
||||
async (requestArg) => {
|
||||
// Verify JWT
|
||||
await this.receptionRef.jwtManager.verifyJWTAndGetData(requestArg.jwt);
|
||||
|
||||
// Get all active global apps
|
||||
const globalApps = await this.CApp.getInstances({
|
||||
type: 'global',
|
||||
});
|
||||
|
||||
const appObjects = await Promise.all(
|
||||
globalApps.map(async (app) => await app.createSavableObject() as plugins.idpInterfaces.data.IGlobalApp)
|
||||
);
|
||||
|
||||
return {
|
||||
apps: appObjects,
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all global apps
|
||||
*/
|
||||
public async getGlobalApps(): Promise<App[]> {
|
||||
return await this.CApp.getInstances({
|
||||
type: 'global',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get app by ID
|
||||
*/
|
||||
public async getAppById(appId: string): Promise<App | null> {
|
||||
return await this.CApp.getInstance({
|
||||
id: appId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed initial global apps (for development/testing)
|
||||
*/
|
||||
public async seedGlobalApps() {
|
||||
const defaultGlobalApps: Partial<plugins.idpInterfaces.data.IGlobalApp>[] = [
|
||||
{
|
||||
id: 'app-foss-global',
|
||||
type: 'global',
|
||||
data: {
|
||||
name: 'foss.global',
|
||||
description: 'Open Source Package Registry and Collaboration Platform',
|
||||
logoUrl: 'https://foss.global/assets/logo.png',
|
||||
appUrl: 'https://foss.global',
|
||||
oauthCredentials: {
|
||||
clientId: 'foss-global-client',
|
||||
clientSecretHash: '', // Will be set when OAuth is configured
|
||||
redirectUris: ['https://foss.global/auth/callback'],
|
||||
allowedScopes: ['openid', 'profile', 'email', 'organizations'],
|
||||
grantTypes: ['authorization_code', 'refresh_token'],
|
||||
},
|
||||
isActive: true,
|
||||
category: 'Development',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'app-task-vc',
|
||||
type: 'global',
|
||||
data: {
|
||||
name: 'task.vc',
|
||||
description: 'Task Management and Project Collaboration',
|
||||
logoUrl: 'https://task.vc/assets/logo.png',
|
||||
appUrl: 'https://task.vc',
|
||||
oauthCredentials: {
|
||||
clientId: 'task-vc-client',
|
||||
clientSecretHash: '',
|
||||
redirectUris: ['https://task.vc/auth/callback'],
|
||||
allowedScopes: ['openid', 'profile', 'email', 'organizations'],
|
||||
grantTypes: ['authorization_code', 'refresh_token'],
|
||||
},
|
||||
isActive: true,
|
||||
category: 'Productivity',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (const appData of defaultGlobalApps) {
|
||||
const existing = await this.CApp.getInstance({ id: appData.id });
|
||||
if (!existing) {
|
||||
const app = new App();
|
||||
app.id = appData.id!;
|
||||
app.type = appData.type!;
|
||||
app.data = appData.data as any;
|
||||
await app.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user