212 lines
6.9 KiB
TypeScript
212 lines
6.9 KiB
TypeScript
import * as plugins from './cloudflare.plugins.js';
|
|
import { logger } from './cloudflare.logger.js';
|
|
import * as interfaces from './interfaces/index.js';
|
|
|
|
// interfaces
|
|
import { WorkerManager } from './cloudflare.classes.workermanager.js';
|
|
import { ZoneManager } from './cloudflare.classes.zonemanager.js';
|
|
|
|
export class CloudflareAccount {
|
|
private authToken: string;
|
|
public preselectedAccountId: string;
|
|
|
|
public workerManager = new WorkerManager(this);
|
|
public zoneManager = new ZoneManager(this);
|
|
|
|
public apiAccount: plugins.cloudflare.Cloudflare;
|
|
|
|
/**
|
|
* constructor sets auth information on the CloudflareAccountInstance
|
|
* @param optionsArg
|
|
*/
|
|
constructor(authTokenArg: string) {
|
|
this.authToken = authTokenArg;
|
|
this.apiAccount = new plugins.cloudflare.Cloudflare({
|
|
apiToken: this.authToken,
|
|
});
|
|
}
|
|
|
|
public async preselectAccountByName(nameArg: string) {
|
|
const accounts = await this.convenience.listAccounts();
|
|
const account = accounts.find((accountArg) => {
|
|
return accountArg.name === nameArg;
|
|
});
|
|
if (account) {
|
|
this.preselectedAccountId = account.id;
|
|
} else {
|
|
throw new Error(`account with name ${nameArg} not found`);
|
|
}
|
|
}
|
|
|
|
public convenience = {
|
|
/**
|
|
* listAccounts
|
|
*/
|
|
listAccounts: async () => {
|
|
const accounts: plugins.ICloudflareTypes['Account'][] = [];
|
|
for await (const account of this.apiAccount.accounts.list()) {
|
|
accounts.push(account as interfaces.ICloudflareApiAccountObject);
|
|
}
|
|
return accounts;
|
|
},
|
|
/**
|
|
* gets a zone id of a domain from cloudflare
|
|
* @param domainName
|
|
*/
|
|
getZoneId: async (domainName: string) => {
|
|
const domain = new plugins.smartstring.Domain(domainName);
|
|
const zoneArray = await this.convenience.listZones(domain.zoneName);
|
|
const filteredResponse = zoneArray.filter((zoneArg) => {
|
|
return zoneArg.name === domainName;
|
|
});
|
|
if (filteredResponse.length >= 1) {
|
|
return filteredResponse[0].id;
|
|
} else {
|
|
logger.log('error', `the domain ${domainName} does not appear to be in this account!`);
|
|
throw new Error(`the domain ${domainName} does not appear to be in this account!`);
|
|
}
|
|
},
|
|
/**
|
|
* gets a record
|
|
* @param domainNameArg
|
|
* @param typeArg
|
|
*/
|
|
getRecord: async (
|
|
domainNameArg: string,
|
|
typeArg: plugins.tsclass.network.TDnsRecordType
|
|
): Promise<plugins.ICloudflareTypes['Record']> => {
|
|
const domain = new plugins.smartstring.Domain(domainNameArg);
|
|
const recordArrayArg = await this.convenience.listRecords(domain.zoneName);
|
|
const filteredResponse = recordArrayArg.filter((recordArg) => {
|
|
return recordArg.type === typeArg && recordArg.name === domainNameArg;
|
|
});
|
|
return filteredResponse[0];
|
|
},
|
|
/**
|
|
* creates a record
|
|
*/
|
|
createRecord: async (
|
|
domainNameArg: string,
|
|
typeArg: plugins.tsclass.network.TDnsRecordType,
|
|
contentArg: string,
|
|
ttlArg = 1
|
|
): Promise<any> => {
|
|
const domain = new plugins.smartstring.Domain(domainNameArg);
|
|
const zoneId = await this.convenience.getZoneId(domain.zoneName);
|
|
const response = await this.apiAccount.dns.records.create({
|
|
zone_id: zoneId,
|
|
type: typeArg as any,
|
|
name: domain.fullName,
|
|
content: contentArg,
|
|
ttl: ttlArg,
|
|
})
|
|
return response;
|
|
},
|
|
/**
|
|
* removes a record from Cloudflare
|
|
* @param domainNameArg
|
|
* @param typeArg
|
|
*/
|
|
removeRecord: async (
|
|
domainNameArg: string,
|
|
typeArg: plugins.tsclass.network.TDnsRecordType
|
|
): Promise<any> => {
|
|
const domain = new plugins.smartstring.Domain(domainNameArg);
|
|
const zoneId = await this.convenience.getZoneId(domain.zoneName);
|
|
const records = await this.convenience.listRecords(domain.zoneName);
|
|
const recordToDelete = records.find((recordArg) => {
|
|
return recordArg.name === domainNameArg && recordArg.type === typeArg;
|
|
});
|
|
if (recordToDelete) {
|
|
await this.apiAccount.dns.records.delete(recordToDelete.id, {
|
|
zone_id: zoneId,
|
|
});
|
|
} else {
|
|
logger.log('warn', `record ${domainNameArg} of type ${typeArg} not found`);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* cleanrecord allows the cleaning of any previous records to avoid unwanted sideeffects
|
|
*/
|
|
cleanRecord: async (domainNameArg: string, typeArg: plugins.tsclass.network.TDnsRecordType) => {
|
|
console.log(`cleaning record for ${domainNameArg}`);
|
|
const records = await this.convenience.listRecords(domainNameArg);
|
|
const recordsToDelete = records.filter((recordArg) => {
|
|
return recordArg.type === typeArg;
|
|
});
|
|
for (const recordToDelete of recordsToDelete) {
|
|
await this.apiAccount.dns.records.delete(recordToDelete.id, {
|
|
zone_id: recordToDelete.zone_id,
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* updates a record
|
|
* @param domainNameArg
|
|
* @param typeArg
|
|
* @param valueArg
|
|
*/
|
|
updateRecord: async (
|
|
domainNameArg: string,
|
|
typeArg: plugins.tsclass.network.TDnsRecordType,
|
|
valueArg
|
|
) => {
|
|
// TODO: implement
|
|
const domain = new plugins.smartstring.Domain(domainNameArg);
|
|
},
|
|
/**
|
|
* list all records of a specified domain name
|
|
* @param domainNameArg - the domain name that you want to get the records from
|
|
*/
|
|
listRecords: async (domainNameArg: string) => {
|
|
const domain = new plugins.smartstring.Domain(domainNameArg);
|
|
const zoneId = await this.convenience.getZoneId(domain.zoneName);
|
|
const records: plugins.ICloudflareTypes['Record'][] = [];
|
|
for await (const record of this.apiAccount.dns.records.list({
|
|
zone_id: zoneId,
|
|
})) {
|
|
records.push(record);
|
|
}
|
|
return records;
|
|
},
|
|
/**
|
|
* list all zones in the associated authenticated account
|
|
* @param domainName
|
|
*/
|
|
listZones: async (domainName?: string) => {
|
|
const zones: plugins.ICloudflareTypes['Zone'][] = [];
|
|
for await (const zone of this.apiAccount.zones.list()) {
|
|
zones.push(zone);
|
|
}
|
|
return zones;
|
|
},
|
|
/**
|
|
* purges a zone
|
|
*/
|
|
purgeZone: async (domainName: string): Promise<void> => {
|
|
const domain = new plugins.smartstring.Domain(domainName);
|
|
const zoneId = await this.convenience.getZoneId(domain.zoneName);
|
|
await this.apiAccount.cache.purge({
|
|
zone_id: zoneId,
|
|
purge_everything: true,
|
|
});
|
|
},
|
|
|
|
// acme convenience functions
|
|
acmeSetDnsChallenge: async (dnsChallenge: plugins.tsclass.network.IDnsChallenge) => {
|
|
await this.convenience.cleanRecord(dnsChallenge.hostName, 'TXT');
|
|
await this.convenience.createRecord(
|
|
dnsChallenge.hostName,
|
|
'TXT',
|
|
dnsChallenge.challenge,
|
|
120
|
|
);
|
|
},
|
|
acmeRemoveDnsChallenge: async (dnsChallenge: plugins.tsclass.network.IDnsChallenge) => {
|
|
await this.convenience.removeRecord(dnsChallenge.hostName, 'TXT');
|
|
},
|
|
};
|
|
}
|