- Added DnsManager and DnsEntry classes to handle DNS entries. - Introduced new interfaces for DNS entry requests and data structures. - Updated Cloudly class to include DnsManager instance. - Enhanced app state to manage DNS entries and actions for creating, updating, and deleting DNS records. - Created UI components for DNS management, including forms for adding and editing DNS entries. - Updated overview and services views to reflect DNS entries. - Added validation and formatting methods for DNS entries.
590 lines
19 KiB
TypeScript
590 lines
19 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import * as domtools from '@design.estate/dees-domtools';
|
|
|
|
const appstate = new plugins.deesDomtools.plugins.smartstate.Smartstate();
|
|
export interface ILoginState {
|
|
identity: plugins.interfaces.data.IIdentity;
|
|
}
|
|
export const loginStatePart: plugins.smartstate.StatePart<unknown, ILoginState> = await appstate.getStatePart<ILoginState>(
|
|
'login',
|
|
{ identity: null },
|
|
'persistent'
|
|
);
|
|
|
|
export const loginAction = loginStatePart.createAction<{ username: string; password: string }>(
|
|
async (statePartArg, payloadArg) => {
|
|
const currentState = statePartArg.getState();
|
|
const trLogin =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.admin.IReq_Admin_LoginWithUsernameAndPassword>(
|
|
'/typedrequest',
|
|
'adminLoginWithUsernameAndPassword'
|
|
);
|
|
const response = await trLogin.fire({
|
|
username: payloadArg.username,
|
|
password: payloadArg.password,
|
|
}).catch(err => {
|
|
console.log(err);
|
|
return {
|
|
...statePartArg.getState(),
|
|
}
|
|
});
|
|
return {
|
|
...currentState,
|
|
...(response.identity ? { identity: response.identity } : {}),
|
|
};
|
|
}
|
|
);
|
|
|
|
export const logoutAction = loginStatePart.createAction(async (statePartArg) => {
|
|
const currentState = statePartArg.getState();
|
|
return {
|
|
...currentState,
|
|
identity: null,
|
|
};
|
|
});
|
|
|
|
export interface IDataState {
|
|
secretGroups?: plugins.interfaces.data.ISecretGroup[];
|
|
secretBundles?: plugins.interfaces.data.ISecretBundle[];
|
|
clusters?: plugins.interfaces.data.ICluster[];
|
|
images?: any[];
|
|
services?: plugins.interfaces.data.IService[];
|
|
deployments?: plugins.interfaces.data.IDeployment[];
|
|
domains?: plugins.interfaces.data.IDomain[];
|
|
dnsEntries?: plugins.interfaces.data.IDnsEntry[];
|
|
mails?: any[];
|
|
logs?: any[];
|
|
s3?: any[];
|
|
dbs?: any[];
|
|
backups?: any[];
|
|
}
|
|
export const dataState = await appstate.getStatePart<IDataState>(
|
|
'data',
|
|
{
|
|
secretGroups: [],
|
|
secretBundles: [],
|
|
clusters: [],
|
|
images: [],
|
|
services: [],
|
|
deployments: [],
|
|
domains: [],
|
|
dnsEntries: [],
|
|
mails: [],
|
|
logs: [],
|
|
s3: [],
|
|
dbs: [],
|
|
backups: [],
|
|
},
|
|
'soft'
|
|
);
|
|
|
|
// Getting data
|
|
export const getAllDataAction = dataState.createAction(async (statePartArg) => {
|
|
let currentState = statePartArg.getState();
|
|
// SecretsGroups
|
|
const trGetSecretGroups =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretgroup.IReq_GetSecretGroups>(
|
|
'/typedrequest',
|
|
'getSecretGroups'
|
|
);
|
|
const response = await trGetSecretGroups.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
secretGroups: response.secretGroups,
|
|
};
|
|
|
|
// SecretBundles
|
|
const trGetSecretBundles =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretbundle.IReq_GetSecretBundles>(
|
|
'/typedrequest',
|
|
'getSecretBundles'
|
|
);
|
|
const responseSecretBundles = await trGetSecretBundles.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
secretBundles: responseSecretBundles.secretBundles,
|
|
};
|
|
|
|
// images
|
|
const trGetImages =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.image.IRequest_GetAllImages>(
|
|
'/typedrequest',
|
|
'getAllImages'
|
|
);
|
|
const responseImages = await trGetImages.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
images: responseImages.images,
|
|
};
|
|
|
|
// Clusters
|
|
const trGetClusters =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.cluster.IReq_Any_Cloudly_GetClusters>(
|
|
'/typedrequest',
|
|
'getClusters'
|
|
);
|
|
const responseClusters = await trGetClusters.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
|
|
currentState = {
|
|
...currentState,
|
|
clusters: responseClusters.clusters,
|
|
}
|
|
|
|
// Services
|
|
const trGetServices =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.service.IRequest_Any_Cloudly_GetServices>(
|
|
'/typedrequest',
|
|
'getServices'
|
|
);
|
|
try {
|
|
const responseServices = await trGetServices.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
services: responseServices?.services || [],
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to fetch services:', error);
|
|
currentState = {
|
|
...currentState,
|
|
services: [],
|
|
};
|
|
}
|
|
|
|
// Deployments
|
|
const trGetDeployments =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.deployment.IReq_Any_Cloudly_GetDeployments>(
|
|
'/typedrequest',
|
|
'getDeployments'
|
|
);
|
|
try {
|
|
const responseDeployments = await trGetDeployments.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
deployments: responseDeployments?.deployments || [],
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to fetch deployments:', error);
|
|
currentState = {
|
|
...currentState,
|
|
deployments: [],
|
|
};
|
|
}
|
|
|
|
// Domains
|
|
const trGetDomains =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.domain.IRequest_Any_Cloudly_GetDomains>(
|
|
'/typedrequest',
|
|
'getDomains'
|
|
);
|
|
try {
|
|
const responseDomains = await trGetDomains.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
domains: responseDomains?.domains || [],
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to fetch domains:', error);
|
|
currentState = {
|
|
...currentState,
|
|
domains: [],
|
|
};
|
|
}
|
|
|
|
// DNS Entries
|
|
const trGetDnsEntries =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.dns.IRequest_Any_Cloudly_GetDnsEntries>(
|
|
'/typedrequest',
|
|
'getDnsEntries'
|
|
);
|
|
try {
|
|
const responseDnsEntries = await trGetDnsEntries.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
dnsEntries: responseDnsEntries?.dnsEntries || [],
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to fetch DNS entries:', error);
|
|
currentState = {
|
|
...currentState,
|
|
dnsEntries: [],
|
|
};
|
|
}
|
|
|
|
return currentState;
|
|
});
|
|
|
|
// Service Actions
|
|
export const createServiceAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { serviceData: plugins.interfaces.data.IService['data'] }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trCreateService =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.service.IRequest_Any_Cloudly_CreateService>(
|
|
'/typedrequest',
|
|
'createService'
|
|
);
|
|
const response = await trCreateService.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
serviceData: payloadArg.serviceData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const updateServiceAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { serviceId: string; serviceData: plugins.interfaces.data.IService['data'] }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trUpdateService =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.service.IRequest_Any_Cloudly_UpdateService>(
|
|
'/typedrequest',
|
|
'updateService'
|
|
);
|
|
const response = await trUpdateService.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
serviceId: payloadArg.serviceId,
|
|
serviceData: payloadArg.serviceData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const deleteServiceAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { serviceId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteService =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.service.IRequest_Any_Cloudly_DeleteServiceById>(
|
|
'/typedrequest',
|
|
'deleteServiceById'
|
|
);
|
|
const response = await trDeleteService.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
serviceId: payloadArg.serviceId,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// SecretGroup Actions
|
|
export const createSecretGroupAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: plugins.interfaces.data.ISecretGroup) => {
|
|
let currentState = statePartArg.getState();
|
|
const trCreateSecretGroup =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretgroup.IReq_CreateSecretGroup>(
|
|
'/typedrequest',
|
|
'createSecretGroup'
|
|
);
|
|
const response = await trCreateSecretGroup.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
secretGroup: payloadArg,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const deleteSecretGroupAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { secretGroupId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteSecretGroup =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretgroup.IReq_DeleteSecretGroupById>(
|
|
'/typedrequest',
|
|
'deleteSecretGroupById'
|
|
);
|
|
const response = await trDeleteSecretGroup.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
secretGroupId: payloadArg.secretGroupId,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// SecretBundle Actions
|
|
export const deleteSecretBundleAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { configBundleId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteConfigBundle =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretbundle.IReq_DeleteSecretBundleById>(
|
|
'/typedrequest',
|
|
'deleteSecretBundleById'
|
|
);
|
|
const response = await trDeleteConfigBundle.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
secretBundleId: payloadArg.configBundleId,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// image actions
|
|
export const createImageAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { imageName: string, description: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trCreateImage =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.image.IRequest_CreateImage>(
|
|
'/typedrequest',
|
|
'createImage'
|
|
);
|
|
const response = await trCreateImage.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
name: payloadArg.imageName,
|
|
description: payloadArg.description,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
...{
|
|
images: [...currentState.images, response.image],
|
|
},
|
|
};
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const deleteImageAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { imageId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteImage =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.image.IRequest_DeleteImage>(
|
|
'/typedrequest',
|
|
'deleteImage'
|
|
);
|
|
const response = await trDeleteImage.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
imageId: payloadArg.imageId,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
...{
|
|
images: currentState.images.filter((image) => image.id !== payloadArg.imageId),
|
|
},
|
|
};
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// Deployment Actions
|
|
export const createDeploymentAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { deploymentData: Partial<plugins.interfaces.data.IDeployment> }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trCreateDeployment =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.deployment.IReq_Any_Cloudly_CreateDeployment>(
|
|
'/typedrequest',
|
|
'createDeployment'
|
|
);
|
|
const response = await trCreateDeployment.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
deploymentData: payloadArg.deploymentData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const updateDeploymentAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { deploymentId: string; deploymentData: Partial<plugins.interfaces.data.IDeployment> }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trUpdateDeployment =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.deployment.IReq_Any_Cloudly_UpdateDeployment>(
|
|
'/typedrequest',
|
|
'updateDeployment'
|
|
);
|
|
const response = await trUpdateDeployment.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
deploymentId: payloadArg.deploymentId,
|
|
deploymentData: payloadArg.deploymentData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const deleteDeploymentAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { deploymentId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteDeployment =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.deployment.IReq_Any_Cloudly_DeleteDeploymentById>(
|
|
'/typedrequest',
|
|
'deleteDeploymentById'
|
|
);
|
|
const response = await trDeleteDeployment.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
deploymentId: payloadArg.deploymentId,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// DNS Actions
|
|
export const createDnsEntryAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { dnsEntryData: plugins.interfaces.data.IDnsEntry['data'] }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trCreateDnsEntry =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.dns.IRequest_Any_Cloudly_CreateDnsEntry>(
|
|
'/typedrequest',
|
|
'createDnsEntry'
|
|
);
|
|
const response = await trCreateDnsEntry.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
dnsEntryData: payloadArg.dnsEntryData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const updateDnsEntryAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { dnsEntryId: string; dnsEntryData: plugins.interfaces.data.IDnsEntry['data'] }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trUpdateDnsEntry =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.dns.IRequest_Any_Cloudly_UpdateDnsEntry>(
|
|
'/typedrequest',
|
|
'updateDnsEntry'
|
|
);
|
|
const response = await trUpdateDnsEntry.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
dnsEntryId: payloadArg.dnsEntryId,
|
|
dnsEntryData: payloadArg.dnsEntryData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const deleteDnsEntryAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { dnsEntryId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteDnsEntry =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.dns.IRequest_Any_Cloudly_DeleteDnsEntry>(
|
|
'/typedrequest',
|
|
'deleteDnsEntry'
|
|
);
|
|
const response = await trDeleteDnsEntry.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
dnsEntryId: payloadArg.dnsEntryId,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// Domain Actions
|
|
export const createDomainAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { domainData: plugins.interfaces.data.IDomain['data'] }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trCreateDomain =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.domain.IRequest_Any_Cloudly_CreateDomain>(
|
|
'/typedrequest',
|
|
'createDomain'
|
|
);
|
|
const response = await trCreateDomain.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
domainData: payloadArg.domainData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const updateDomainAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { domainId: string; domainData: plugins.interfaces.data.IDomain['data'] }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trUpdateDomain =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.domain.IRequest_Any_Cloudly_UpdateDomain>(
|
|
'/typedrequest',
|
|
'updateDomain'
|
|
);
|
|
const response = await trUpdateDomain.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
domainId: payloadArg.domainId,
|
|
domainData: payloadArg.domainData,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const deleteDomainAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { domainId: string }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trDeleteDomain =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.domain.IRequest_Any_Cloudly_DeleteDomain>(
|
|
'/typedrequest',
|
|
'deleteDomain'
|
|
);
|
|
const response = await trDeleteDomain.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
domainId: payloadArg.domainId,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
export const verifyDomainAction = dataState.createAction(
|
|
async (statePartArg, payloadArg: { domainId: string; verificationMethod?: 'dns' | 'http' | 'email' | 'manual' }) => {
|
|
let currentState = statePartArg.getState();
|
|
const trVerifyDomain =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.domain.IRequest_Any_Cloudly_VerifyDomain>(
|
|
'/typedrequest',
|
|
'verifyDomain'
|
|
);
|
|
const response = await trVerifyDomain.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
domainId: payloadArg.domainId,
|
|
verificationMethod: payloadArg.verificationMethod,
|
|
});
|
|
currentState = await dataState.dispatchAction(getAllDataAction, null);
|
|
return currentState;
|
|
}
|
|
);
|
|
|
|
// cluster
|
|
export const addClusterAction = dataState.createAction(
|
|
async (
|
|
statePartArg,
|
|
payloadArg: {
|
|
clusterName: string;
|
|
setupMode?: 'manual' | 'hetzner' | 'aws' | 'digitalocean';
|
|
}
|
|
) => {
|
|
let currentState = statePartArg.getState();
|
|
const trAddCluster =
|
|
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.cluster.IRequest_CreateCluster>(
|
|
'/typedrequest',
|
|
'createCluster'
|
|
);
|
|
const response = await trAddCluster.fire({
|
|
identity: loginStatePart.getState().identity,
|
|
...payloadArg,
|
|
});
|
|
currentState = {
|
|
...currentState,
|
|
...{
|
|
clusters: [...currentState.clusters, response.cluster],
|
|
},
|
|
}
|
|
return currentState;
|
|
}
|
|
);
|