fix(deps): Update dependencies to latest versions

This commit is contained in:
2024-08-25 14:29:26 +02:00
parent acc642adf9
commit 0ec665516d
25 changed files with 1661 additions and 1404 deletions

View File

@ -1,8 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@serve.zone/cloudly',
version: '1.1.6',
version: '1.1.7',
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
}

View File

@ -9,6 +9,7 @@ export const getUsers = async (cloudlyRef: Cloudly) => {
users.push({
id: 'envadmin',
data: {
type: 'human',
username: envAdminUser.split(':')[0],
password: envAdminUser.split(':')[1],
role: 'admin',

View File

@ -34,7 +34,7 @@ export class LetsencryptConnector {
},
mongoDescriptor: this.cloudlyRef.config.data.mongoDescriptor,
});
await this.smartacme.init().catch(err => {
await this.smartacme.start().catch(err => {
console.error('error in init', err);
console.log(`trying again in a few minutes`)
});

View File

@ -9,6 +9,7 @@ import { User } from './classes.user.js';
export interface IJwtData {
userId: string;
status: 'loggedIn' | 'loggedOut';
expiresAt: number;
}
export class CloudlyAuthManager {
@ -33,12 +34,12 @@ export class CloudlyAuthManager {
await this.smartjwtInstance.init();
const kvStore = await this.cloudlyRef.config.appData.getKvStore();
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = await kvStore.readKey('jwtKeys');
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = (await kvStore.readKey('jwtKeypair')) as plugins.tsclass.network.IJwtKeypair;
if (!existingJwtKeys) {
await this.smartjwtInstance.createNewKeyPair();
const newJwtKeys = this.smartjwtInstance.getKeyPairAsJson();
await kvStore.writeKey('jwtKeys', newJwtKeys);
await kvStore.writeKey('jwtKeypair', newJwtKeys);
} else {
this.smartjwtInstance.setKeyPairAsJson(existingJwtKeys);
}
@ -48,6 +49,7 @@ export class CloudlyAuthManager {
'adminLoginWithUsernameAndPassword',
async (dataArg) => {
let jwt: string;
let expiresAtTimestamp: number = Date.now() + 3600 * 1000 * 24 * 7;
const user = await User.findUserByUsernameAndPassword(dataArg.username, dataArg.password);
if (!user) {
logger.log('warn', 'login failed');
@ -55,11 +57,19 @@ export class CloudlyAuthManager {
jwt = await this.smartjwtInstance.createJWT({
userId: user.id,
status: 'loggedIn',
expiresAt: expiresAtTimestamp,
});
logger.log('success', 'login successful');
}
return {
jwt,
identity: {
jwt,
userId: user.id,
name: user.data.username,
expiresAt: expiresAtTimestamp,
role: user.data.role,
type: user.data.type,
},
};
}
)
@ -68,14 +78,33 @@ export class CloudlyAuthManager {
public async stop () {}
public adminJwtGuard = new plugins.smartguard.Guard<{jwt: string}>(async (dataArg) => {
const jwt = dataArg.jwt;
public validIdentityGuard = new plugins.smartguard.Guard<{identity: plugins.servezoneInterfaces.data.IIdentity}>(async (dataArg) => {
const jwt = dataArg.identity.jwt;
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
const expired = jwtData.expiresAt < Date.now();
plugins.smartexpect.expect(jwtData.status).setFailMessage('user not logged in').toEqual('loggedIn');
plugins.smartexpect.expect(expired).setFailMessage(`jwt expired`).toBeFalse();
plugins.smartexpect.expect(dataArg.identity.expiresAt).setFailMessage(`expiresAt >>identity valid until:${dataArg.identity.expiresAt}, but jwt says: ${jwtData.expiresAt}<< has been tampered with`).toEqual(jwtData.expiresAt);
plugins.smartexpect.expect(dataArg.identity.userId).setFailMessage('userId has been tampered with').toEqual(jwtData.userId);
if (expired) {
throw new Error('identity is expired');
}
return true;
}, {
failedHint: 'identity is not valid.',
name: 'validIdentityGuard',
});
public adminIdentityGuard = new plugins.smartguard.Guard<{identity: plugins.servezoneInterfaces.data.IIdentity}>(async (dataArg) => {
await plugins.smartexpect.expectAsync(this.validIdentityGuard.exec(dataArg)).toBeTrue();
const jwt = dataArg.identity.jwt;
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
const user = await this.CUser.getInstance({id: jwtData.userId});
const isAdminBool = user.data.role === 'admin';
console.log(`user is admin: ${isAdminBool}`);
return isAdminBool;
}, {
failedHint: 'user is not admin.'
failedHint: 'user is not admin.',
name: 'adminIdentityGuard',
})
}

View File

@ -19,9 +19,5 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
public id: string;
@plugins.smartdata.svDb()
public data: {
role: 'admin' | 'user';
username: string;
password: string;
};
public data: plugins.servezoneInterfaces.data.IUser['data'];
}

View File

@ -1,5 +1,5 @@
import * as plugins from '../plugins.js';
export class Cert extends plugins.smartdata.SmartDataDbDoc<> {
export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, Cert> {
}

View File

@ -22,12 +22,14 @@ export class ClusterManager {
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_CreateCluster>(
new plugins.typedrequest.TypedHandler('createCluster', async (dataArg) => {
const cluster = await this.storeCluster({
// TODO: guards
const cluster = await this.createCluster({
id: plugins.smartunique.uniSimple('cluster'),
data: {
userId: null,
name: dataArg.clusterName,
jumpCode: plugins.smartunique.uniSimple('cluster'),
jumpCodeUsedAt: null,
initialJumpToken: plugins.smartunique.uniSimple('initialJumpToken'),
initialJumpTokenUsedAt: null,
acmeInfo: null,
cloudlyUrl: `https://${this.cloudlyRef.config.data.publicUrl}:${this.cloudlyRef.config.data.publicPort}/`,
servers: [],
@ -57,7 +59,7 @@ export class ClusterManager {
// delete cluster
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_DeleteCluster>(
new plugins.typedrequest.TypedHandler('deleteCluster', async (reqDataArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], reqDataArg);
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqDataArg);
await this.deleteCluster(reqDataArg.clusterId);
return {
success: true,
@ -80,25 +82,24 @@ export class ClusterManager {
// TODO: implement getclusterConfigByServerIp
}
public async getClusterConfigBy_JumpCode(jumpCodeArg: string) {
public async getClusterBy_JumpCode(initialJumpTokenArg: string) {
await this.ready.promise;
return await Cluster.getInstance({
data: {
jumpCode: jumpCodeArg,
initialJumpToken: initialJumpTokenArg,
},
});
}
public async getClusterConfigBy_ClusterIdentifier(
clusterIdentifier: plugins.servezoneInterfaces.data.IClusterIdentifier
public async getClusterBy_Identity(
clusterIdentity: plugins.servezoneInterfaces.data.IIdentity
) {
await this.ready.promise;
return await Cluster.getInstance({
id: clusterIdentifier.clusterId,
data: {
name: clusterIdentifier.clusterName,
userId: clusterIdentity.userId,
},
});
}
@ -128,13 +129,20 @@ export class ClusterManager {
* @param configName
* @param configObjectArg
*/
public async storeCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
let clusterInstance = await Cluster.getInstance({ id: configObjectArg.id });
if (!clusterInstance) {
clusterInstance = await Cluster.fromConfigObject(configObjectArg);
} else {
Object.assign(clusterInstance, configObjectArg);
public async createCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
// TODO: guards
// lets create the cluster user
const clusterUser = new this.cloudlyRef.authManager.CUser();
clusterUser.id = await this.cloudlyRef.authManager.CUser.getNewId();
clusterUser.data = {
role: 'cluster',
type: 'machine',
}
await clusterUser.save();
Object.assign(configObjectArg, {
userId: clusterUser.id,
});
const clusterInstance = await Cluster.fromConfigObject(configObjectArg);
await clusterInstance.save();
return clusterInstance;
}

View File

@ -15,22 +15,37 @@ export class CloudlyCoreflowManager {
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByJumpCode>(
new plugins.typedrequest.TypedHandler('getIdentityByJumpCode', async (requestData) => {
const clusterConfig =
await this.cloudlyRef.clusterManager.getClusterConfigBy_JumpCode(
const cluster =
await this.cloudlyRef.clusterManager.getClusterBy_JumpCode(
requestData.jumpCode
);
if (!clusterConfig) {
throw new plugins.typedrequest.TypedResponseError('The supplied jumpCode is not valid.');
if (!cluster) {
throw new plugins.typedrequest.TypedResponseError('The supplied jumpCode is not valid. No cluster found.');
}
const user = await this.cloudlyRef.authManager.CUser.getInstance({
id: cluster.data.userId,
});
if (!user) {
throw new plugins.typedrequest.TypedResponseError('The supplied jumpCode is not valid. No user found.');
}
const expiryTimestamp = Date.now() + 3600 * 1000 * 24 * 365;
return {
clusterIdentifier: {
clusterId: clusterConfig.id,
clusterName: clusterConfig.data.name,
identity: {
name: cluster.data.name,
role: 'cluster',
type: 'machine',
userId: cluster.data.userId,
expiresAt: expiryTimestamp,
clusterId: cluster.id,
clusterName: cluster.data.name,
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
status: 'loggedIn',
userId: 'cluster:' + clusterConfig.id, // TODO: create real users for clusters
userId: cluster.data.userId,
expiresAt: expiryTimestamp,
})
},
};
@ -42,16 +57,16 @@ export class CloudlyCoreflowManager {
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetClusterConfig>(
'getClusterConfig',
async (dataArg) => {
const clusterIdentifier = dataArg.clusterIdentifier;
const identity = dataArg.identity;
console.log('trying to get clusterConfigSet');
console.log(dataArg);
const clusterConfigSet =
await this.cloudlyRef.clusterManager.getClusterConfigBy_ClusterIdentifier(
clusterIdentifier
const cluster =
await this.cloudlyRef.clusterManager.getClusterBy_Identity(
identity
);
console.log('got cluster config and sending it back to coreflow');
return {
configData: await clusterConfigSet.createSavableObject(),
configData: await cluster.createSavableObject(),
deploymentDirectives: [],
};
}
@ -60,14 +75,14 @@ export class CloudlyCoreflowManager {
// lets enable getting of certificates
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetSslCertificate>(
'getSslCertificate',
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetCertificateForDomain>(
'getCertificateForDomain',
async (dataArg) => {
console.log(`got request for certificate ${dataArg.requiredCertName}`);
console.log(`incoming API request for certificate ${dataArg.domainName}`);
const cert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
dataArg.requiredCertName
dataArg.domainName
);
console.log(`got certificate ready for reponse ${dataArg.requiredCertName}`);
console.log(`got certificate ready for reponse ${dataArg.domainName}`);
return {
certificate: await cert.createSavableObject(),
};

View File

@ -26,7 +26,7 @@ export class ImageManager {
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_CreateImage>(
'createImage',
async (reqArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], reqArg);
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg);
const image = await this.CImage.create({
name: reqArg.name,
description: reqArg.description,
@ -43,7 +43,7 @@ export class ImageManager {
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_DeleteImage>(
'deleteImage',
async (reqArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], reqArg);
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg);
const image = await this.CImage.getInstance({
id: reqArg.imageId,
});
@ -57,7 +57,7 @@ export class ImageManager {
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetAllImages>(
'getAllImages',
async (requestArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], requestArg);
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], requestArg);
const images = await this.CImage.getInstances({});
return {
images: await Promise.all(

View File

@ -39,8 +39,8 @@ export class CloudlySecretManager {
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_GetConfigBundlesAndSecretGroups>(
'adminGetConfigBundlesAndSecretGroups',
async (dataArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], dataArg);
dataArg.jwt
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
dataArg.identity.jwt
const secretBundles = await SecretBundle.getInstances({});
const secretGroups = await SecretGroup.getInstances({});
return {

View File

@ -1,4 +1,5 @@
import * as plugins from '../plugins.js';
import { ServiceManager } from './classes.servicemanager.js';
export class Service extends plugins.smartdata.SmartDataDbDoc<Service, plugins.servezoneInterfaces.data.IService, ServiceManager> {

View File

@ -33,6 +33,7 @@ import * as smartclickhouse from '@push.rocks/smartclickhouse';
import * as smartdata from '@push.rocks/smartdata';
import * as smartdelay from '@push.rocks/smartdelay';
import * as smartexit from '@push.rocks/smartexit';
import * as smartexpect from '@push.rocks/smartexpect';
import * as smartfile from '@push.rocks/smartfile';
import * as smartguard from '@push.rocks/smartguard';
import * as smartjson from '@push.rocks/smartjson';
@ -57,6 +58,7 @@ export {
smartclickhouse,
smartdata,
smartexit,
smartexpect,
smartdelay,
smartfile,
smartguard,