mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
import { GraphQLClient } from 'graphql-request'
|
|
import { SignJWT } from 'jose'
|
|
import { getLogger, Logger } from 'log4js'
|
|
import * as v from 'valibot'
|
|
import { CONFIG } from '../../config'
|
|
import { LOG4JS_BASE_CATEGORY } from '../../config/const'
|
|
import { HieroId, Uuidv4 } from '../../schemas/typeGuard.schema'
|
|
import { homeCommunityGraphqlQuery, setHomeCommunityTopicId } from './graphql'
|
|
import { type Community, communitySchema } from './output.schema'
|
|
|
|
// Source: https://refactoring.guru/design-patterns/singleton/typescript/example
|
|
// and ../federation/client/FederationClientFactory.ts
|
|
/**
|
|
* A Singleton class defines the `getInstance` method that lets clients access
|
|
* the unique singleton instance.
|
|
*/
|
|
export class BackendClient {
|
|
private static instance: BackendClient
|
|
client: GraphQLClient
|
|
logger: Logger
|
|
urlValue: string
|
|
|
|
/**
|
|
* The Singleton's constructor should always be private to prevent direct
|
|
* construction calls with the `new` operator.
|
|
*/
|
|
private constructor() {
|
|
this.logger = getLogger(`${LOG4JS_BASE_CATEGORY}.client.BackendClient`)
|
|
this.urlValue = `http://localhost:${CONFIG.PORT}`
|
|
this.logger.addContext('url', this.urlValue)
|
|
|
|
this.client = new GraphQLClient(this.urlValue, {
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
method: 'GET',
|
|
jsonSerializer: {
|
|
parse: JSON.parse,
|
|
stringify: JSON.stringify,
|
|
},
|
|
})
|
|
}
|
|
|
|
public get url(): string {
|
|
return this.url
|
|
}
|
|
|
|
/**
|
|
* The static method that controls the access to the singleton instance.
|
|
*
|
|
* This implementation let you subclass the Singleton class while keeping
|
|
* just one instance of each subclass around.
|
|
*/
|
|
public static getInstance(): BackendClient {
|
|
if (!BackendClient.instance) {
|
|
BackendClient.instance = new BackendClient()
|
|
}
|
|
return BackendClient.instance
|
|
}
|
|
|
|
public async getHomeCommunityDraft(): Promise<Community> {
|
|
this.logger.info('check home community on backend')
|
|
const { data, errors } = await this.client.rawRequest<{ homeCommunity: Community }>(
|
|
homeCommunityGraphqlQuery,
|
|
{},
|
|
await this.getRequestHeader(),
|
|
)
|
|
if (errors) {
|
|
throw errors[0]
|
|
}
|
|
return v.parse(communitySchema, data.homeCommunity)
|
|
}
|
|
|
|
public async setHomeCommunityTopicId(uuid: Uuidv4, hieroTopicId: HieroId): Promise<Community> {
|
|
this.logger.info('update home community on backend')
|
|
const { data, errors } = await this.client.rawRequest<{ updateHomeCommunity: Community }>(
|
|
setHomeCommunityTopicId,
|
|
{ uuid, hieroTopicId },
|
|
await this.getRequestHeader(),
|
|
)
|
|
if (errors) {
|
|
throw errors[0]
|
|
}
|
|
return v.parse(communitySchema, data.updateHomeCommunity)
|
|
}
|
|
|
|
private async getRequestHeader(): Promise<{
|
|
authorization: string
|
|
}> {
|
|
return {
|
|
authorization: 'Bearer ' + (await this.createJWTToken()),
|
|
}
|
|
}
|
|
|
|
private async createJWTToken(): Promise<string> {
|
|
const secret = new TextEncoder().encode(CONFIG.JWT_SECRET)
|
|
const token = await new SignJWT({ gradidoID: 'dlt-connector', 'urn:gradido:claim': true })
|
|
.setProtectedHeader({ alg: 'HS256' })
|
|
.setIssuedAt()
|
|
.setIssuer('urn:gradido:issuer')
|
|
.setAudience('urn:gradido:audience')
|
|
.setExpirationTime('1m')
|
|
.sign(secret)
|
|
return token
|
|
}
|
|
}
|