Skip to content

Commit e1ae3f6

Browse files
committed
update config and structure for daemon
1 parent 81696f8 commit e1ae3f6

File tree

10 files changed

+140
-39
lines changed

10 files changed

+140
-39
lines changed

backends.example/01ad/config.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ description: 'Backend for AD'
44
active: 0
55
actions:
66
CHANGEPWD:
7-
exec: "changepasswd"
7+
script: "changepasswd"
88
onError: 'stop'
99
RESETPWD:
10-
exec: "resetpasswd"
10+
script: "resetpasswd"
1111
onError: 'stop'
12-
ADDIDENT:
13-
exec: 'dummy.sh'
14-
UPDATEIDENT:
15-
exec: 'dummy.sh'
12+
IDENTITY_CREATE:
13+
script: 'dummy.sh'
14+
IDENTITY_UPDATE:
15+
script: 'dummy.sh'
1616
DELIDENT:
17-
exec: 'dummy.sh'
17+
script: 'dummy.sh'
1818
PING:
19-
exec: 'ping.sh'
19+
script: 'ping.sh'

src/_common/backend-initializer/config.initializer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default async function configInitializer(backendsPath: string): Promise<B
2828
const config = YAML.parse(data);
2929

3030
try {
31-
config.path = path.dirname(file);
31+
if (!config.path) config.path = path.dirname(file);
3232
const schema = plainToInstance(BackendConfigDto, config);
3333
await validateOrReject(schema, {
3434
whitelist: true,
Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import { IsString, IsEnum, IsNumber, IsNotEmpty } from 'class-validator';
1+
import { IsString, IsEnum, IsBoolean, IsNotEmpty } from 'class-validator';
22

33
export enum ActionType {
4-
// noinspection JSUnusedGlobalSymbols
5-
LISTBACKEND = 'LISTBACKEND',
6-
CHANGEPWD = 'CHANGEPWD',
7-
RESETPWD = 'RESETPWD',
8-
ADDIDENT = 'ADDIDENT',
9-
UPDATEIDENT = 'UPDATEIDENT',
10-
DELIDENT = 'DELIDENT',
4+
LIST_BACKENDS = 'LIST_BACKENDS',
5+
IDENTITY_CREATE = 'IDENTITY_CREATE',
6+
IDENTITY_UPDATE = 'IDENTITY_UPDATE',
7+
IDENTITY_DELETE = 'IDENTITY_DELETE',
8+
IDENTITY_PASSWORD_RESET = 'IDENTITY_PASSWORD_RESET',
9+
IDENTITY_PASSWORD_CHANGE = 'IDENTITY_PASSWORD_CHANGE',
1110
}
1211

1312
export class BackendActionDto {
1413
@IsString()
15-
public exec: string;
14+
@IsNotEmpty()
15+
public script: string;
1616

1717
@IsString()
18-
@IsEnum(['pass', 'failed'])
18+
@IsEnum(['continue', 'stop'])
1919
public onError: string;
2020
}
2121

@@ -25,15 +25,19 @@ export class BackendConfigDto {
2525
public name: string;
2626

2727
@IsString()
28-
public description: string;
28+
public description?: string;
2929

30+
/**
31+
* Path to the backend script
32+
* If not set, it will be the directory of the config file
33+
*/
3034
@IsString()
35+
@IsNotEmpty()
3136
public path: string;
3237

33-
@IsNumber()
38+
@IsBoolean()
3439
@IsNotEmpty()
35-
@IsEnum([0, 1])
36-
public active: number;
40+
public active: boolean;
3741

3842
public actions: Record<ActionType, BackendActionDto>;
3943
}

src/backend-runner/_executors/catch-all.executor.ts

Whitespace-only changes.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { BackendRunnerService } from '../backend-runner.service';
2+
import { ExecutorInterface } from '../executors.interface';
3+
4+
export class ListBackendsExecutor implements ExecutorInterface {
5+
public constructor(public service: BackendRunnerService) {}
6+
7+
public async execute({}): Promise<void> {
8+
this.service.logger.log('execute LISTBACKEND');
9+
return {
10+
status: 0,
11+
jobId: job.id,
12+
data: this.service.backendsConfig,
13+
};
14+
}
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* BackendCodesEnum
3+
*
4+
* @description Enum for backend codes
5+
* @see https://tldp.org/LDP/abs/html/exitcodes.html
6+
* @see https://www.linuxdoc.org/LDP/abs/html/exitcodes.html
7+
* @see https://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
8+
*/
9+
export enum BackendCodesEnum {
10+
OK = 0,
11+
GENERIC_ERROR = 1<<0,
12+
GENERIC_STOPPED = 1<<1,
13+
CONNECTION_ERROR = 1<<2,
14+
INVALID_LOGIN = 1<<3,
15+
INVALID_CREDENTIALS = 1<<4,
16+
}
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
export interface BackendResultInterface {
22
backend: string;
33
status: number;
4-
output?: string;
5-
error?: string;
4+
output?: BackendResultInfoInterface;
5+
error?: BackendResultInfoInterface;
66
}
7+
8+
export interface BackendResultInfoInterface {
9+
status: number;
10+
message?: string;
11+
data?: object;
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { BackendResultInterface } from "./backend-result.interface";
2+
3+
export interface WorkerResultInterface {
4+
jobId: string;
5+
status: number;
6+
data: WorkerResultInfoInterface;
7+
}
8+
9+
export interface WorkerResultInfoInterface {
10+
[backendName: string]: Partial<BackendResultInterface>;
11+
}

src/backend-runner/backend-runner.service.ts

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
1+
import { Injectable, Logger, OnModuleInit, OnApplicationBootstrap } from '@nestjs/common';
22
import { ConfigService } from '@nestjs/config';
33
import { Job, Worker } from 'bullmq';
44
import { ActionType, BackendConfigDto } from './_dto/backend-config.dto';
@@ -7,32 +7,47 @@ import executorTask from '../_common/tasks/executor.task';
77
import { BackendResultInterface } from './_interfaces/backend-result.interface';
88
import { ExecutorConfigInterface } from '~/_common/interfaces/executor-config.interface';
99
import { join } from 'path';
10+
import { ExecutorInterface } from './executors.interface';
11+
import { ListBackendsExecutor } from './_executors/list-backends.executor';
1012

1113
@Injectable()
12-
export class BackendRunnerService implements OnModuleInit {
13-
private readonly backendsConfig: BackendConfigDto[] = [];
14-
private readonly logger = new Logger(BackendRunnerService.name);
14+
export class BackendRunnerService implements OnApplicationBootstrap, OnModuleInit {
15+
private readonly _backendsConfig: BackendConfigDto[] = [];
16+
private readonly _logger = new Logger(BackendRunnerService.name);
17+
18+
protected executors: Map<string, ExecutorInterface> = new Map<string, ExecutorInterface>();
1519

1620
public constructor(private readonly config: ConfigService) {
17-
this.backendsConfig = this.config.get<BackendConfigDto[]>('backendsConfig');
21+
this._backendsConfig = this.config.get<BackendConfigDto[]>('backendsConfig');
22+
}
23+
24+
public get backendsConfig() {
25+
return this._backendsConfig;
26+
}
27+
28+
public get logger() {
29+
return this._logger;
1830
}
1931

2032
public async onModuleInit() {
21-
this.logger.log('BackendRunnerService initialized');
33+
this.executors.set(ActionType.LIST_BACKENDS, new ListBackendsExecutor(this));
34+
this.logger.log('OnModuleInit initialized 🔴');
35+
}
2236

37+
public async onApplicationBootstrap() {
2338
const worker = new Worker(
2439
this.config.get<string>('nameQueue'),
2540
async (job) => {
2641
let status = 0;
2742
const data = [];
28-
for await (const backend of this.backendsConfig) {
43+
for await (const backend of this._backendsConfig) {
2944
switch (job.name) {
30-
case ActionType.LISTBACKEND: {
45+
case ActionType.LIST_BACKENDS: {
3146
return await this.listBackends(job);
3247
}
3348

3449
default: {
35-
if (backend.active !== 1) {
50+
if (!backend.active) {
3651
this.logger.warn(`backend ${backend.name} is not active`);
3752
continue;
3853
}
@@ -59,24 +74,44 @@ export class BackendRunnerService implements OnModuleInit {
5974
},
6075
);
6176
await worker.run();
77+
this.logger.log('OnApplicationBootstrap initialized 🔴');
6278
}
6379

6480
public async listBackends(job: Job) {
6581
this.logger.log('execute LISTBACKEND');
6682
return {
6783
status: 0,
6884
jobId: job.id,
69-
data: this.backendsConfig,
85+
data: this._backendsConfig,
7086
};
7187
}
7288

7389
public async executeBackend(job: Job, backend: BackendConfigDto): Promise<BackendResultInterface> {
7490
const process = await executorTask(join(backend.path, 'bin', backend.actions[job.name].exec), job, {
7591
...this.config.get<ExecutorConfigInterface>('backendExecutorConfig'),
7692
});
77-
return {
78-
backend: backend.name,
79-
...process,
80-
};
93+
try {
94+
if (process.status !== 0) {
95+
return {
96+
backend: backend.name,
97+
status: process.status,
98+
error: JSON.parse(process.output),
99+
};
100+
}
101+
return {
102+
backend: backend.name,
103+
status: process.status,
104+
output: JSON.parse(process.output),
105+
};
106+
} catch (e) {
107+
return {
108+
backend: backend.name,
109+
status: process.status,
110+
error: {
111+
status: process.status,
112+
message: process.error,
113+
},
114+
};
115+
}
81116
}
82117
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { BackendRunnerService } from './backend-runner.service';
2+
3+
export interface ExecutorExecuteOptionsInterface {}
4+
5+
export interface ExecutorExecuteResponseInterface {
6+
jobId: string;
7+
status: number;
8+
}
9+
10+
export interface ExecutorInterface {
11+
readonly service: BackendRunnerService;
12+
13+
execute(context: ExecutorExecuteOptionsInterface): Promise<ExecutorExecuteResponseInterface>;
14+
}

0 commit comments

Comments
 (0)