Files
phishingclub/frontend/src/lib/api/api.js
T
2026-04-23 20:27:30 +02:00

3323 lines
81 KiB
JavaScript

import {
getJSON,
postJSON,
postMultipart,
patchJSON,
deleteJSON,
deleteReq,
newResponse,
putJSON
} from './client.js';
/**
* Represents the response object returned by the API functions.
* @typedef {Object} ApiResponse
* @property {boolean} success - Indicates whether the request was successful.
* @property {number} statusCode - The status code of the response.
* @property {string} error - The error message, if any.
* @property {any} data - The data returned by the request.
*/
/**
* @typedef {object} APISenderHeader
* @property {string} [id]
* @property {string} key
* @property {string} value
* @property {boolean} isRequestHeader
* @property {string} [apiSenderID]
*/
/**
* TableURLParams is a type that represents the query parameters for a table.
*
* @typedef {object} TableURLParams
* @property {number} [currentPage]
* @property {number} [perPage]
* @property {string} [sortBy]
* @property {string} [sortOrder]
* @property {string} [search]
*/
/**
* Calculates the offset for the specified page and per page count.
*
* @param {number} currentPage
* @param {number} perPage
* @returns {number}
*/
const getOffset = (currentPage, perPage) => {
return (currentPage - 1) * perPage;
};
const appendQuery = (query) => {
if (!query) {
return '_'; // append after this method hack
}
// extract only the state properties we need, avoiding methods and internal properties
// handle both tableURLParams objects and plain objects safely
const currentPage = query.currentPage || query.page || 1;
const perPage = query.perPage || 10;
const sortBy = query.sortBy || '';
const sortOrder = query.sortOrder || '';
const search = query.search || '';
const includeTest = query.includeTest;
const offset = getOffset(currentPage, perPage);
let urlQuery = `offset=${offset}&limit=${perPage}`;
if (sortBy) {
// normalize the sortby field by lowercasing and replacing spacing with underscores
const normalizedSortBy = sortBy.toLowerCase().replace(/\s+/g, '_');
urlQuery += `&sortBy=${normalizedSortBy}`;
}
if (sortOrder) {
urlQuery += `&sortOrder=${sortOrder}`;
} else {
urlQuery += `&sortOrder=asc`;
}
if (search) {
urlQuery += `&search=${search}`;
}
if (includeTest === true) {
urlQuery += `&includeTest=true`;
} else if (includeTest === false) {
urlQuery += `&includeTest=false`;
}
return urlQuery;
};
/**
* API is for interacting with the backend API.
* Use API.instance to get a singleton instance of the API class.
*/
export class API {
/**
* @param {API|null} _instance
*/
static #_instance = null;
/**
* instance is the singleton instance of the API class.
*
* @returns {API}
*/
static get instance() {
if (!API.#_instance) {
API.#_instance = new API();
}
return API.#_instance;
}
/**
* The base URL or PATH of the API.
*
* @type {string}
*/
#_url;
/**
* The version of the API.
*
* @type {string}
*/
#_version;
/**
* Creates a new API instance.
*
* @param {string} url
*/
constructor(url = '/api', version = '/v1') {
this.#_version = version;
this.#_url = url;
}
/**
* Constructs the full URL for the specified path.
*
* @param {string} path
* @returns {string}
*/
getPath(path) {
return `${this.#_url}${this.#_version}${path}`;
}
/**
* builds a query arg for the company ID to
* be appended to the path or a empty string if the companyID is not provided.
*/
appendCompanyQuery(companyID) {
if (!companyID) {
return '';
}
return `&${this.companyQuery(companyID)}`;
}
companyQuery(companyID) {
if (!companyID) {
return '';
}
return `companyID=${companyID}`;
}
/**
* builds a query arg for the type ID to
* be appended to the path or a empty string if the typeID is not provided.
*/
appendTypeQuery(typeID) {
if (!typeID) {
return '';
}
return `&typeID=${typeID}`;
}
/**
* application is the API for application related operations.
*/
application = {
/**
* Feature flags - get the features the application is build with
*
* @returns {Promise<ApiResponse>}
*/
features: async () => {
return await getJSON(this.getPath('/features'));
},
/**
* Install the application.
*
* @param {string} username
* @param {string} userFullname
* @param {string} newPassword
* @returns {Promise<ApiResponse>}
*/
install: async (username, userFullname, newPassword) => {
return await postJSON(this.getPath(`/install`), {
username,
userFullname,
newPassword
});
},
/**
* Health check endpoint
* @returns {Promise<boolean>}
*/
health: async () => {
const res = await fetch(this.getPath('/healthz'), {
method: 'GET'
});
return res.status === 200;
},
/**
* Check if update is available (cached)
* @returns {Promise<ApiResponse>}
*/
isUpdateAvailableCached: async () => {
return await getJSON(this.getPath(`/update/available/cached`));
},
/**
* Check if update is available (manual check)
* @returns {Promise<ApiResponse>}
*/
isUpdateAvailable: async () => {
return await getJSON(this.getPath(`/update/available`));
},
/**
* Get update details
* @returns {Promise<ApiResponse>}
*/
getUpdateDetails: async () => {
return await getJSON(this.getPath(`/update`));
},
/**
* Performs an update
* @returns {Promise<ApiResponse>}
*/
runUpdate: async () => {
return await postJSON(this.getPath(`/update`));
},
/**
* Create a backup
* @returns {Promise<ApiResponse>}
*/
createBackup: async () => {
return await postJSON(this.getPath(`/backup/create`));
},
/**
* List available backups
* @returns {Promise<ApiResponse>}
*/
listBackups: async () => {
return await getJSON(this.getPath(`/backup/list`));
},
/**
* Download a backup file
* @param {string} filename - name of the backup file
* @returns {Promise<Blob>}
*/
downloadBackup: async (filename) => {
const response = await fetch(
this.getPath(`/backup/download/${encodeURIComponent(filename)}`),
{
method: 'GET',
credentials: 'same-origin'
}
);
if (!response.ok) {
throw new Error(`Failed to download backup: ${response.statusText}`);
}
return await response.blob();
},
/**
* Install example templates from GitHub during setup
* @returns {Promise<ApiResponse>}
*/
installTemplates: async () => {
return await postJSON(this.getPath(`/install/templates`));
}
};
/**
* asset is the API for asset (static files) related operations.
*/
asset = {
/**
* Get assets for a domain.
*
* @param {string} domain
* @param {string|null} companyID
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getByDomain: async (domain, companyID, options) => {
return await getJSON(
this.getPath(
`/asset/domain/${domain}?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get asset by id
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/asset/${id}`));
},
/**
* Get asset by id in base64 with mime type
*
* @param {string} domain
* @param {string} path
* @returns {Promise<ApiResponse>}
*/
getRaw: async (domain, path) => {
return await getJSON(this.getPath(`/asset/view/domain/${domain}/${path}`));
},
/**
* Get all assets for a domain using pagination.
*
* @param {*} data form data
* @returns {Promise<ApiResponse>}
*/
upload: async (data) => {
const res = await fetch(this.getPath(`/asset`), {
method: 'POST',
// content-type is set automatically by the browser
body: data
});
// TODO all of these to json things can fail we need to do something more
const body = await res.json();
return newResponse(body.success, res.status, body.error, body.data);
},
/**
* Update an asset
*
* @param {string} id
* @param {string} name
* @param {string} description
* @returns {Promise<ApiResponse>}
*/
update: async (id, name, description) => {
return await patchJSON(this.getPath(`/asset/${id}`), {
name: name,
description: description
});
},
/**
* Get all assets for a domain using pagination.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/asset/${id}`));
}
};
/**
* atttachment is the API for attachment related operations.
* @type {Object}
*/
attachment = {
/**
* Get attachments.
*
* @param {string|null} companyID can be null for global context
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getByContext: async (companyID, options) => {
return await getJSON(
this.getPath(`/attachment?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get an attachment by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/attachment/${id}`));
},
/**
* Get the content and mime type of an attachment by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getContentByID: async (id) => {
return await getJSON(this.getPath(`/attachment/${id}/content`));
},
/**
*
* @param {object} attachment
* @param {string} attachment.id
* @param {string} attachment.name
* @param {string} attachment.description
* @param {Boolean} attachment.embeddedContent
* @returns {Promise<ApiResponse>}
*/
update: async ({ id, name, description, embeddedContent }) => {
return await patchJSON(this.getPath(`/attachment/${id}`), {
name: name,
description: description,
embeddedContent: embeddedContent
});
},
/**
* Upload a new attachment.
*
* @param {FormData} data
* @returns {Promise<ApiResponse>}
*/
upload: async (data) => {
const res = await fetch(this.getPath(`/attachment`), {
method: 'POST',
// content-type is set automatically by the browser
body: data
});
// TODO all of these to json things can fail we need to do something more
const body = await res.json();
return newResponse(body.success, res.status, body.error, body.data);
},
/**
* Delete an attachment by its ID.
*
* @param {string} id
* @returns
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/attachment/${id}`));
}
};
/**
* campaign is the API for campaign related operations.
* @type {Object}
* @returns {Promise<ApiResponse>}
*/
campaign = {
/**
* @param {string} campaignID
* @returns {Promise<ApiResponse>}
*/
anonymize: async (campaignID) => {
return postJSON(this.getPath(`/campaign/${campaignID}/anonymize`));
},
/**
* @param {string} campaignID
* @returns {Promise<ApiResponse>}
*/
close: async (campaignID) => {
return postJSON(this.getPath(`/campaign/${campaignID}/close`));
},
/**
* @param {string} campaignID
* @returns
*/
exportEvents: async (campaignID) => {
window.open(this.getPath(`/campaign/${campaignID}/export/events`), '_blank');
},
/**
* Export campaign submissions as CSV
* @param {string} campaignID
* @returns
*/
exportSubmissions: async (campaignID) => {
window.open(this.getPath(`/campaign/${campaignID}/export/submissions`), '_blank');
},
/**
*
* @param {object} campaign
* @param {string} [campaign.companyID] uuid
* @param {string} campaign.templateID uuid
* @param {string} campaign.name
* @param {boolean} [campaign.saveSubmittedData]
* @param {boolean} [campaign.saveBrowserMetadata]
* @param {boolean} [campaign.isAnonymous]
* @param {boolean} [campaign.isTest]
* @param {boolean} [campaign.obfuscate]
* @param {string} campaign.sortField
* @param {string} campaign.sortOrder
* @param {string} campaign.sendStartAt
* @param {string} campaign.sendEndAt
* @param {string} [campaign.closeAt]
* @param {string} [campaign.anonymizeAt]
* @param {string} [campaign.scheduleAt]
* @param {string[]} campaign.recipientGroupIDs []uuid
* @param {string[]} campaign.allowDenyIDs []uuid
* @param {string} campaign.denyPageID uuid
* @param {string} campaign.evasionPageID uuid
* @param {Array} [campaign.webhooks] array of webhook configs
* @param {Array} [campaign.constraintWeekDays]
* @param {string} [campaign.constraintStartTime]
* @param {string} [campaign.constraintEndTime]
* @param {number} [campaign.jitterMin]
* @param {number} [campaign.jitterMax]
* @returns {Promise<ApiResponse>}
*/
create: async ({
companyID,
templateID,
name,
saveSubmittedData,
saveBrowserMetadata,
isAnonymous,
isTest,
obfuscate,
sortField,
sortOrder,
sendStartAt,
sendEndAt,
closeAt,
anonymizeAt,
scheduleAt,
recipientGroupIDs,
allowDenyIDs,
denyPageID,
evasionPageID,
webhooks,
constraintWeekDays,
constraintStartTime,
constraintEndTime,
jitterMin,
jitterMax
}) => {
return await postJSON(this.getPath('/campaign'), {
companyID,
templateID,
name,
isAnonymous,
isTest,
obfuscate,
saveSubmittedData,
saveBrowserMetadata,
sortField,
sortOrder,
sendStartAt,
sendEndAt,
closeAt,
anonymizeAt,
scheduleAt,
recipientGroupIDs,
allowDenyIDs,
denyPageID,
evasionPageID,
webhooks,
constraintWeekDays,
constraintStartTime,
constraintEndTime,
jitterMin,
jitterMax
});
},
/**
* @param {Object} campaign
* @param {string} campaign.id uuid
* @param {string} campaign.name
* @param {boolean} [campaign.saveSubmittedData]
* @param {boolean} [campaign.saveBrowserMetadata]
* @param {boolean} [campaign.isAnonymous]
* @param {boolean} [campaign.isTest]
* @param {boolean} [campaign.obfuscate]
* @param {string} campaign.sortField
* @param {string} campaign.sortOrder
* @param {string} campaign.sendStartAt
* @param {string} campaign.sendEndAt
* @param {string} [campaign.closeAt]
* @param {string} [campaign.anonymizeAt]
* @param {string} [campaign.scheduleAt]
* @param {string} campaign.templateID uuid
* @param {string[]} campaign.recipientGroupIDs []uuid
* @param {string[]} campaign.allowDenyIDs []uuid
* @param {string} campaign.denyPageID uuid
* @param {string} campaign.evasionPageID uuid
* @param {Array} [campaign.webhooks] array of webhook configs
* @param {Array} [campaign.constraintWeekDays]
* @param {string} [campaign.constraintStartTime]
* @param {string} [campaign.constraintEndTime]
* @param {number} [campaign.jitterMin]
* @param {number} [campaign.jitterMax]
* @returns {Promise<ApiResponse>}
*/
update: async ({
id,
templateID,
name,
saveSubmittedData,
saveBrowserMetadata,
isAnonymous,
isTest,
obfuscate,
sortField,
sortOrder,
sendStartAt,
sendEndAt,
closeAt,
anonymizeAt,
scheduleAt,
recipientGroupIDs,
allowDenyIDs,
denyPageID,
evasionPageID,
webhooks,
constraintWeekDays,
constraintStartTime,
constraintEndTime,
jitterMin,
jitterMax
}) => {
return await postJSON(this.getPath(`/campaign/${id}`), {
templateID,
name,
isAnonymous,
isTest,
obfuscate,
saveSubmittedData,
saveBrowserMetadata,
sortField,
sortOrder,
sendStartAt,
sendEndAt,
closeAt,
anonymizeAt,
scheduleAt,
recipientGroupIDs,
allowDenyIDs,
denyPageID,
evasionPageID,
webhooks,
constraintWeekDays,
constraintStartTime,
constraintEndTime,
jitterMin,
jitterMax
});
},
/**
* Get a campaign by ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/campaign/${id}`));
},
/**
* Get a campaign by name.
*
* @param {string} name
* @returns {Promise<ApiResponse>}
*/
getByName: async (name, companyID = null) => {
return await getJSON(
this.getPath(
`/campaign/name/${name}?${appendQuery(null)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get all campaigns using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/campaign?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get all campaigns using pagination.
*
* @param {TableURLParams} options
* @param {string} start RFC3339NANO
* @param {string} end RFC3339NANO
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getWithinDates: async (start, end, options, companyID = null) => {
return await getJSON(
this.getPath(
`/campaign/calendar?${appendQuery(options)}${this.appendCompanyQuery(companyID)}&start=${start}&end=${end}`
)
);
},
/**
* Get all active campaigns using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllActive: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/campaign/active?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get all upcoming campaigns using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllUpcoming: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/campaign/upcoming?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get all active campaigns using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllFinished: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/campaign/finished?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get all campaign recipients.
*
* @param {string} campaignID
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getAllCampaignRecipients: async (campaignID, options) => {
return await getJSON(
this.getPath(`/campaign/${campaignID}/recipients?${appendQuery(options)}`)
);
},
/**
* Get all event types.
*
* @returns {Promise<ApiResponse>}
*/
getAllEventTypes: async () => {
return await getJSON(this.getPath(`/campaign/event-types`));
},
/**
* Get all events by campaign ID.
*
* @param {string} campaignID
* @param {TableURLParams} options
* @param {string} since RFC3339NANO
* @returns {Promise<ApiResponse>}
*/
getAllEventsByCampaignID: async (campaignID, options, since = '') => {
return await getJSON(
this.getPath(`/campaign/${campaignID}/events?${appendQuery(options)}&since=${since}`)
);
},
/**
* Get all events across campaigns.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllEvents: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/campaign/events?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get campaigns stats
* if no company ID is provided it retrieves the global stats including all companies
*/
getStats: async (companyID = null, options = {}) => {
return await getJSON(
this.getPath(
`/campaign/statistics?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get campaign result stats
* @param {string} campaignID
* @returns {Promise<ApiResponse>}
*/
getResultStats: async (campaignID) => {
return await getJSON(this.getPath(`/campaign/${campaignID}/statistics`));
},
/**
* Get campaign recipient email.
*
* @param {string} campaignRecipientID
* @returns {Promise<ApiResponse>}
*/
getEmail: async (campaignRecipientID) => {
return await getJSON(this.getPath(`/campaign/recipient/${campaignRecipientID}/email`));
},
/**
* Set email sent to now
*
* @param {string} campaignRecipient
* @returns {Promise<ApiResponse>}
*/
setEmailSent: async (campaignRecipient) => {
return await postJSON(this.getPath(`/campaign/recipient/${campaignRecipient}/sent`));
},
/**
* Send message to campaign recipient (works for both email and API senders)
*
* @param {string} campaignRecipientID
* @returns {Promise<ApiResponse>}
*/
sendMessage: async (campaignRecipientID) => {
return await postJSON(this.getPath(`/campaign/recipient/${campaignRecipientID}/send`));
},
/**
* Send email to campaign recipient (alias for sendMessage for backward compatibility)
*
* @param {string} campaignRecipientID
* @returns {Promise<ApiResponse>}
*/
sendEmail: async (campaignRecipientID) => {
return await postJSON(this.getPath(`/campaign/recipient/${campaignRecipientID}/send`));
},
/**
* Get campaign recipient landingpage URL.
*
* @param {string} campaignRecipientID
* @return {Promise<ApiResponse>}
*/
getURL: async (campaignRecipientID) => {
return await getJSON(this.getPath(`/campaign/recipient/${campaignRecipientID}/url`));
},
/**
* Delete all device codes for a campaign so every recipient gets a fresh
* code (and picks up any proxy change) on their next page visit.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
deleteDeviceCodes: async (id) => {
return await deleteJSON(this.getPath(`/campaign/${id}/device-codes`));
},
/**
* Delete a campaign.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/campaign/${id}`));
},
/**
* Delete a campaign event.
*
* @param {string} eventID
* @returns {Promise<ApiResponse>}
*/
deleteEvent: async (eventID) => {
return await deleteJSON(this.getPath(`/campaign/event/${eventID}`));
},
/**
* Get campaign statistics by campaign ID.
*
* @param {string} campaignID
* @returns {Promise<ApiResponse>}
*/
getCampaignStats: async (campaignID) => {
return await getJSON(this.getPath(`/campaign/${campaignID}/stats`));
},
/**
* Get all campaign statistics.
*
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllCampaignStats: async (companyID = null) => {
const companyQuery = companyID ? `?${this.companyQuery(companyID)}` : '';
return await getJSON(this.getPath(`/campaign/stats/all${companyQuery}`));
},
/**
* Get all manual campaign statistics (those without campaignID).
*
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getManualCampaignStats: async (companyID = null) => {
const companyQuery = companyID ? `?${this.companyQuery(companyID)}` : '';
return await getJSON(this.getPath(`/campaign/stats/manual${companyQuery}`));
},
/**
* Create manual campaign statistics.
*
* @param {object} stats
* @param {string} stats.campaignName
* @param {string} [stats.companyId]
* @param {number} stats.totalRecipients
* @param {number} stats.emailsSent
* @param {number} stats.trackingPixelLoaded
* @param {number} stats.websiteVisits
* @param {number} stats.dataSubmissions
* @param {number} stats.reported
* @param {string} [stats.templateName]
* @param {string} [stats.campaignType]
* @param {string} [stats.campaignStartDate] - ISO date string
* @param {string} [stats.campaignEndDate] - ISO date string
* @param {string} [stats.campaignClosedAt] - ISO date string
* @returns {Promise<ApiResponse>}
*/
createStats: async (stats) => {
return await postJSON(this.getPath('/campaign/stats'), stats);
},
/**
* Update manual campaign statistics by ID.
*
* @param {string} statsID
* @param {object} stats
* @param {string} stats.campaignName
* @param {string} [stats.companyId]
* @param {number} stats.totalRecipients
* @param {number} stats.emailsSent
* @param {number} stats.trackingPixelLoaded
* @param {number} stats.websiteVisits
* @param {number} stats.dataSubmissions
* @param {number} stats.reported
* @param {string} [stats.templateName]
* @param {string} [stats.campaignType]
* @param {string} [stats.campaignStartDate] - ISO date string
* @param {string} [stats.campaignEndDate] - ISO date string
* @param {string} [stats.campaignClosedAt] - ISO date string
* @returns {Promise<ApiResponse>}
*/
updateStats: async (statsID, stats) => {
return await putJSON(this.getPath(`/campaign/stats/${statsID}`), stats);
},
/**
* Delete manual campaign statistics by ID.
*
* @param {string} statsID
* @returns {Promise<ApiResponse>}
*/
deleteStats: async (statsID) => {
return await deleteJSON(this.getPath(`/campaign/stats/${statsID}`));
}
};
/**
* campain templates is the API for campaign template related operations.
*
* @type {Object}
*/
campaignTemplate = {
/**
* Get a campaign template by its ID.
*
* @param {string} id
* @param {boolean} full retrieve related data
* @returns {Promise<ApiResponse>}
*/
getByID: async (id, full = false) => {
let p = this.getPath(`/campaign/template/${id}`);
if (full) {
p += '?full';
}
return await getJSON(p);
},
/**
* Get all campaign templates using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null, usableOnly = false) => {
return await getJSON(
this.getPath(
`/campaign/template?${appendQuery(options)}${this.appendCompanyQuery(companyID)}&usableOnly=${usableOnly}`
)
);
},
/**
* Create a new campaign template.
*
* @param {object} template
* @param {string} template.name
* @param {string} template.companyID
* @param {string} template.domainID
* @param {string} template.beforeLandingPageID
* @param {string} template.beforeLandingProxyID
* @param {string} template.afterLandingPageID
* @param {string} template.afterLandingProxyID
* @param {string} template.landingPageID
* @param {string} template.landingProxyID
* @param {string} template.smtpConfigurationID
* @param {string} template.apiSenderID
* @param {string} template.afterLandingPageRedirectURL
* @param {string} template.urlIdentifierID
* @param {string} template.stateIdentifierID
* @param {string} template.urlPath
* @param {string} template.emailID
* @returns {Promise<ApiResponse>}
*/
create: async ({
name,
companyID,
domainID,
beforeLandingPageID,
beforeLandingProxyID,
afterLandingPageID,
afterLandingProxyID,
landingPageID,
landingProxyID,
smtpConfigurationID,
apiSenderID,
urlIdentifierID,
stateIdentifierID,
afterLandingPageRedirectURL,
emailID: emailID,
urlPath: urlPath
}) => {
return await postJSON(this.getPath('/campaign/template'), {
name: name,
companyID: companyID,
domainID: domainID,
beforeLandingPageID: beforeLandingPageID,
beforeLandingProxyID: beforeLandingProxyID,
afterLandingPageID: afterLandingPageID,
afterLandingProxyID: afterLandingProxyID,
landingPageID: landingPageID,
landingProxyID: landingProxyID,
smtpConfigurationID: smtpConfigurationID,
apiSenderID: apiSenderID,
afterLandingPageRedirectURL: afterLandingPageRedirectURL,
urlIdentifierID: urlIdentifierID,
stateIdentifierID: stateIdentifierID,
emailID: emailID,
urlPath: urlPath
});
},
/**
* Update a campaign template.
*
* @param {Object} template
* @param {string} template.id
* @param {string} template.name
* @param {string} template.companyID
* @param {string} template.domainID
* @param {string} template.beforeLandingPageID
* @param {string} template.beforeLandingProxyID
* @param {string} template.afterLandingPageID
* @param {string} template.afterLandingProxyID
* @param {string} template.landingPageID
* @param {string} template.landingProxyID
* @param {string} template.smtpConfigurationID
* @param {string} template.apiSenderID
* @param {string} template.afterLandingPageRedirectURL
* @param {string} template.emailID
* @param {string} template.urlIdentifierID
* @param {string} template.stateIdentifierID
* @param {string} template.urlPath
* @returns {Promise<ApiResponse>}
*/
update: async ({
id,
name,
companyID,
domainID,
beforeLandingPageID,
beforeLandingProxyID,
afterLandingPageID,
afterLandingProxyID,
landingPageID,
landingProxyID,
smtpConfigurationID,
apiSenderID,
afterLandingPageRedirectURL,
emailID: emailID,
urlIdentifierID: urlIdentifierID,
stateIdentifierID: stateIdentifierID,
urlPath: urlPath
}) => {
return await postJSON(this.getPath(`/campaign/template/${id}`), {
name: name,
companyID: companyID,
domainID: domainID,
beforeLandingPageID: beforeLandingPageID,
beforeLandingProxyID: beforeLandingProxyID,
afterLandingPageID: afterLandingPageID,
afterLandingProxyID: afterLandingProxyID,
landingPageID: landingPageID,
landingProxyID: landingProxyID,
smtpConfigurationID: smtpConfigurationID,
apiSenderID: apiSenderID,
afterLandingPageRedirectURL: afterLandingPageRedirectURL,
emailID: emailID,
urlIdentifierID: urlIdentifierID,
stateIdentifierID: stateIdentifierID,
urlPath: urlPath
});
},
/**
* Delete a campaign template.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/campaign/template/${id}`));
}
};
/**
* company is the API for company related operations.
*
* @type {Object}
*/
company = {
/**
* Get a company by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/company/${id}`));
},
/**
* Exports a companies data
*
* @param {string} id
* @returns
*/
export: async (id) => {
window.open(this.getPath(`/company/${id ? id : 'shared'}/export`), '_blank');
},
/**
* Get all companies using pagination
*
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getAll: async (options) => {
return await getJSON(this.getPath(`/company?${appendQuery(options)}`));
},
/**
* Create a new company.
*
* @param {string} name
* @param {string} comment
* @returns {Promise<ApiResponse>}
*/
create: async (name, comment) => {
return await postJSON(this.getPath(`/company`), {
name: name,
comment: comment
});
},
/**
* Update a company.
*
* @param {string} id
* @param {string} name
* @param {string} comment
* @returns {Promise<ApiResponse>}
*/
update: async (id, name, comment) => {
return await postJSON(this.getPath(`/company/${id}`), {
name: name,
comment: comment
});
},
/**
* Delete a company.
*
* @param {string} id
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/company/${id}`));
},
/**
* Get the auto-prune orphaned recipients setting for a company.
* Returns only the per-company enabled flag.
*
* @param {string} id - company ID
* @returns {Promise<ApiResponse>}
*/
getAutoPrune: async (id) => {
return await getJSON(this.getPath(`/company/${id}/option/auto-prune`));
},
/**
* Set the auto-prune orphaned recipients setting for a company.
*
* @param {string} id - company ID
* @param {boolean} enabled
* @returns {Promise<ApiResponse>}
*/
setAutoPrune: async (id, enabled) => {
return await postJSON(this.getPath(`/company/${id}/option/auto-prune`), {
enabled: enabled
});
}
};
/**
* domain is the API for domain related operations.
*/
domain = {
/**
* creates a new domain.
*
* @param {object} domain
* @param {string} domain.name
* @param {string} domain.type
* @param {string} domain.proxyTargetDomain
* @param {boolean} domain.managedTLS
* @param {boolean} domain.ownManagedTLS
* @param {boolean} domain.selfSignedTLS
* @param {string} domain.ownManagedTLSKey
* @param {string} domain.ownManagedTLSPem
* @param {boolean} domain.hostWebsite
* @param {string} domain.pageContent
* @param {string} domain.pageNotFoundContent
* @param {string} domain.redirectURL
* @param {string} domain.companyID
* @returns {Promise<ApiResponse>}
*/
create: async ({
name,
type,
proxyTargetDomain,
managedTLS,
ownManagedTLS,
selfSignedTLS,
ownManagedTLSKey,
ownManagedTLSPem,
hostWebsite,
pageContent,
pageNotFoundContent,
redirectURL,
companyID
}) => {
return await postJSON(this.getPath('/domain/'), {
name: name,
type: type,
proxyTargetDomain: proxyTargetDomain,
managedTLS: managedTLS,
ownManagedTLS: ownManagedTLS,
selfSignedTLS: selfSignedTLS,
ownManagedTLSKey: ownManagedTLSKey,
ownManagedTLSPem: ownManagedTLSPem,
hostWebsite: hostWebsite,
pageContent: pageContent,
pageNotFoundContent: pageNotFoundContent,
redirectURL: redirectURL,
companyID: companyID
});
},
/**
* updates a domain.
*
* @param {object} domain
* @param {string} domain.id
* @param {string} [domain.type]
* @param {string} [domain.proxyTargetDomain]
* @param {boolean} domain.managedTLS
* @param {boolean} domain.ownManagedTLS
* @param {boolean} domain.selfSignedTLS
* @param {string} domain.ownManagedTLSKey
* @param {string} domain.ownManagedTLSPem
* @param {boolean} [domain.hostWebsite]
* @param {string} [domain.pageContent]
* @param {string} [domain.pageNotFoundContent]
* @param {string} [domain.redirectURL]
* @param {string} domain.companyID
* @returns {Promise<ApiResponse>}
*/
update: async ({
id,
type,
proxyTargetDomain,
managedTLS,
ownManagedTLS,
selfSignedTLS,
ownManagedTLSKey,
ownManagedTLSPem,
hostWebsite,
pageContent,
pageNotFoundContent,
redirectURL,
companyID
}) => {
const payload = {
managedTLS: managedTLS,
ownManagedTLS: ownManagedTLS,
selfSignedTLS: selfSignedTLS,
ownManagedTLSKey: ownManagedTLSKey,
ownManagedTLSPem: ownManagedTLSPem,
companyID: companyID
};
// conditionally add fields if they are provided
if (type !== undefined) payload.type = type;
if (proxyTargetDomain !== undefined) payload.proxyTargetDomain = proxyTargetDomain;
if (hostWebsite !== undefined) payload.hostWebsite = hostWebsite;
if (pageContent !== undefined) payload.pageContent = pageContent;
if (pageNotFoundContent !== undefined) payload.pageNotFoundContent = pageNotFoundContent;
if (redirectURL !== undefined) payload.redirectURL = redirectURL;
return await postJSON(this.getPath(`/domain/${id}`), payload);
},
/**
* deletes a domain.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteReq(this.getPath(`/domain/${id}`));
},
/**
* gets a domain by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/domain/${id}`));
},
/**
* get a domain by its name.
*
* @param {string} name
* @returns {Promise<ApiResponse>}
*/
getByName: async (name) => {
return await getJSON(this.getPath(`/domain/name/${name}`));
},
/**
* get domains
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/domain?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* get domains subsets
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllSubset: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/domain/subset?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* get domains subsets excluding proxy domains
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllSubsetWithoutProxies: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/domain/subset/noproxies?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
}
};
/**
* page s the API for page related operations.
*/
page = {
/**
* Get a page by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/page/${id}`));
},
/**
* Get all pages using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/page?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get page content by id
*/
getContentByID: async (id) => {
return await getJSON(this.getPath(`/page/${id}/content`));
},
/**
* Get all pages using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getOverviews: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/page/overview?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Create a new page.
*
* @param {string} name
* @param {string} content
* @param {string} companyID
* @returns {Promise<ApiResponse>}
*/
create: async (name, content, companyID) => {
const payload = {
name: name,
content: content,
companyID: companyID
};
return await postJSON(this.getPath('/page'), payload);
},
/**
* Update a page.
*
* @param {string} id
* @param {object} page
* @param {string} page.name
* @param {string} page.content
* @returns {Promise<ApiResponse>}
*/
update: async (id, page) => {
return await patchJSON(this.getPath(`/page/${id}`), page);
},
/**
* Delete a page.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/page/${id}`));
}
};
/**
* log is the API for log related operations.
*/
log = {
/**
* Get the log level.
*
* @returns {Promise<ApiResponse>}
*/
getLevel: async () => {
return await getJSON(this.getPath('/log'));
},
/**
* Set the log level.
*
* @param {string} level
* @param {string} dbLevel
* @returns {Promise<ApiResponse>}
*/
setLevel: async (level, dbLevel) => {
return await postJSON(this.getPath('/log'), {
level: level,
dbLevel: dbLevel
});
},
/**
* Test the log levels. Can only be observed in the backend logs.
*
* @returns {Promise<ApiResponse>}
*/
testLevels: async () => {
return await getJSON(this.getPath('/log/test'));
}
};
/**
* email is the API for email related operations.
*/
email = {
/**
* Add attachments to a email.
*
* @param {string} emailID
* @param {Array<{id: string, isInline: boolean}>} attachments - Array of attachment objects with id and isInline flag
* @returns {Promise<ApiResponse>}
*/
addAttachments: async (emailID, attachments) => {
return await postJSON(this.getPath(`/email/${emailID}/attachment`), {
attachments: attachments
});
},
/**
* Remove an attachment from a email.
*
* @param {string} emailID
* @param {string} attachmentID
* @returns
*/
removeAttachment: async (emailID, attachmentID) => {
return await deleteJSON(this.getPath(`/email/${emailID}/attachment`), {
attachmentID: attachmentID
});
},
/**
* Get a email by ID.
*
* @param {string} id
* @param {string|null} [companyID]
* @returns {Promise<ApiResponse>}
*/
getByID: async (id, companyID = null) => {
const companyQuery = companyID ? `?${this.companyQuery(companyID)}` : '';
return await getJSON(this.getPath(`/email/${id}${companyQuery}`));
},
/**
* Get the content of a email by ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getContentByID: async (id) => {
return await getJSON(this.getPath(`/email/${id}/content`));
},
/**
* Get all emails using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/email?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get all email overviews
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getOverviews: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/email/overview?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Send a test email
*
*
* @param {object} params
* @param {string} params.id
* @param {string} params.smtpID
* @param {string} params.domainID
* @param {string} params.recipientID
* @returns {Promise<ApiResponse>}
*/
sendTest: async ({ id: emailID, smtpID, domainID, recipientID }) => {
return await postJSON(this.getPath(`/email/${emailID}/send-test`), {
smtpID: smtpID,
recipientID: recipientID,
domainID: domainID
});
},
/**
* Create a new email.
*
* @param {Object} email
* @param {string} email.name
* @param {string} email.content
* @param {string} email.mailEnvelopeFrom
* @param {string} email.mailHeaderFrom
* @param {string} email.mailHeaderSubject
* @param {bool} email.addTrackingPixel
* @param {string} [email.companyID]
* @returns {Promise<ApiResponse>}
*/
create: async (email) => {
return await postJSON(this.getPath('/email'), email);
},
/**
* Update a email.
*
* @param {Object} email
* @param {string} email.id
* @param {string} [email.name]
* @param {string} [email.content]
* @param {string} [email.mailEnvelopeFrom]
* @param {string} [email.mailHeaderFrom]
* @param {string} [email.mailHeaderSubject]
* @param {boolean} [email.addTrackingPixel]
* @param {string} [email.companyID]
* @returns {Promise<ApiResponse>}
*/
update: async ({
id,
name,
content,
mailEnvelopeFrom,
mailHeaderFrom,
mailHeaderSubject,
addTrackingPixel,
companyID
}) => {
return await postJSON(this.getPath(`/email/${id}`), {
name: name,
content: content,
mailEnvelopeFrom: mailEnvelopeFrom,
mailHeaderSubject: mailHeaderSubject,
mailHeaderFrom: mailHeaderFrom,
addTrackingPixel: addTrackingPixel,
companyID: companyID
});
},
/**
* Delete a email.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/email/${id}`));
}
};
/**
* session is the API for session related operations.
*/
session = {
/**
* Ping session.
*
* @returns {Promise<ApiResponse>}
*/
ping: async () => {
return await getJSON(this.getPath(`/session/ping`));
},
/**
* Revoke a session.
*
* @param {string} sessionID
* @returns {Promise<ApiResponse>}
*/
revoke: async (sessionID) => {
return await deleteReq(this.getPath(`/session/${sessionID}`));
}
};
/**
* smtpConfiguration is the API for SMTPConfiguration related operations.
*/
smtpConfiguration = {
/**
* Get all SMTPConfigurations using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID) => {
return await getJSON(
this.getPath(
`/smtp-configuration?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get a SMTPConfiguration by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/smtp-configuration/${id}`));
},
/**
* Send a test email using the configuration.
*
* @param {string} id
* @param {Object} data
* @param {string} data.email
* @param {string} data.mailFrom
* @returns {Promise<ApiResponse>}
*/
sendTestEmail: async (id, data) => {
return await postJSON(this.getPath(`/smtp-configuration/${id}/test-email`), data);
},
/**
* Create a new SMTPConfiguration.
*
* @param {Object} configuration
* @param {string} configuration.name
* @param {string} configuration.host
* @param {number} configuration.port
* @param {string} configuration.username
* @param {string} configuration.password
* @param {boolean} configuration.ignoreCertErrors
* @param {string} configuration.companyID
* @returns
*/
create: async (configuration) => {
return await postJSON(this.getPath('/smtp-configuration'), configuration);
},
/**
* Update a SMTPConfiguration.
*
* @param {Object} configuration
* @param {string} configuration.id
* @param {string} configuration.name
* @param {string} configuration.host
* @param {number} configuration.port
* @param {string} configuration.username
* @param {string} configuration.password
* @param {boolean} configuration.ignoreCertErrors
* @param {string} configuration.companyID
* @returns {Promise<ApiResponse>}
*/
update: async (configuration) => {
return await patchJSON(
this.getPath(`/smtp-configuration/${configuration.id}`),
configuration
);
},
/**
* Delete a SMTPConfiguration.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/smtp-configuration/${id}`));
},
/**
* Add a new SMTP header to a SMTPConfiguration.
*
* @param {string} smtpConfigurationID
* @param {string} key
* @param {string} value
* @returns {Promise<ApiResponse>}
*/
addHeader: async (smtpConfigurationID, key, value) => {
return await patchJSON(this.getPath(`/smtp-configuration/${smtpConfigurationID}/header`), {
key: key,
value: value
});
},
/**
* Delete a SMTP header from a SMTPConfiguration.
*
* @param {string} smtpConfigurationID
* @param {string} headerID
* @returns {Promise<ApiResponse>}
*/
deleteHeader: async (smtpConfigurationID, headerID) => {
return await deleteJSON(
this.getPath(`/smtp-configuration/${smtpConfigurationID}/header/${headerID}`)
);
}
};
/**
* oauthProvider is the API for OAuth Provider related operations.
*/
oauthProvider = {
/**
* Get all OAuth Providers using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID) => {
return await getJSON(
this.getPath(`/oauth-provider?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get an OAuth Provider by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/oauth-provider/${id}`));
},
/**
* Create a new OAuth Provider.
*
* @param {Object} provider
* @param {string} provider.name
* @param {string} provider.clientID
* @param {string} provider.clientSecret
* @param {string} provider.authURL
* @param {string} provider.tokenURL
* @param {string} provider.scopes
* @param {string} provider.companyID
* @returns {Promise<ApiResponse>}
*/
create: async (provider) => {
return await postJSON(this.getPath('/oauth-provider'), provider);
},
/**
* Update an OAuth Provider.
*
* @param {Object} provider
* @param {string} provider.id
* @param {string} provider.name
* @param {string} provider.clientID
* @param {string} provider.clientSecret
* @param {string} provider.authURL
* @param {string} provider.tokenURL
* @param {string} provider.scopes
* @param {string} provider.companyID
* @returns {Promise<ApiResponse>}
*/
update: async (provider) => {
return await patchJSON(this.getPath(`/oauth-provider/${provider.id}`), provider);
},
/**
* Delete an OAuth Provider.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/oauth-provider/${id}`));
},
/**
* Get the authorization URL for an OAuth Provider.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getAuthorizationURL: async (id) => {
return await getJSON(this.getPath(`/oauth-authorize/${id}`));
},
/**
* Remove authorization tokens from an OAuth Provider.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
removeAuthorization: async (id) => {
return await postJSON(this.getPath(`/oauth-provider/${id}/remove-authorization`), {});
},
/**
* Import authorized OAuth tokens.
*
* @param {Array<{access_token: string, refresh_token: string, client_id: string, expires_at: number, name: string, user: string, scope: string, token_url?: string, created_at?: number}>} tokens
* @returns {Promise<ApiResponse>}
*/
importTokens: async (tokens) => {
return await postJSON(this.getPath('/oauth-provider/import-tokens'), tokens);
},
/**
* Export OAuth tokens for a provider.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
exportTokens: async (id) => {
return await getJSON(this.getPath(`/oauth-provider/${id}/export-tokens`));
}
};
/**
* user is the API for user related operations - these actions also affect the user's sessions
*/
user = {
/**
* Create a new user
*
* @param {Object} user
* @param {string} user.username
* @param {string} user.password
* @param {string} user.email
* @param {string} user.fullname
* @returns {Promise<ApiResponse>}
*/
create: async ({ username, password, email, fullname }) => {
return await postJSON(this.getPath(`/user`), {
username,
password,
email,
fullname
});
},
/**
* Delete a user by ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/user/${id}`));
},
/**
* Get all users using pagination.
*
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getAll: async (options) => {
return await getJSON(this.getPath(`/user?${appendQuery(options)}`));
},
/**
* Get a user by ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
* */
getByID: async (id) => {
return await getJSON(this.getPath(`/user/${id}`));
},
/**
* Get user's sessions.
*
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getAllSessions: async (options) => {
return await getJSON(this.getPath(`/user/sessions?${appendQuery(options)}`));
},
/**
* Update a user.
*
* @param {Object} user
* @param {string} user.id
* @param {string} user.username
* @param {string} user.email
* @param {string} user.fullname
* @returns {Promise<ApiResponse>}
*/
updateByID: async ({ id, username, email, fullname }) => {
return await postJSON(this.getPath(`/user/${id}`), {
username: username,
email: email,
name: fullname
});
},
/**
* Get user's api key in a masked format.
*
* @returns {Promise<ApiResponse>}
*/
getAPIKeyMasked: async () => {
return await getJSON(this.getPath(`/user/api`));
},
/**
* Upsert the logged-in users api key
*
* @returns {Promise<ApiResponse>}
*/
upsertAPIKey: async () => {
return await postJSON(this.getPath(`/user/api`), {});
},
/**
* Removes the logged-in users api key
*
* @returns {Promise<ApiResponse>}
*/
removeAPIKey: async () => {
return await deleteJSON(this.getPath(`/user/api`), {});
},
/**
* Login.
*
* @param {string} username
* @param {string} password
* @returns {Promise<ApiResponse>}
*/
login: async (username, password) => {
return await postJSON(this.getPath(`/user/login`), {
username,
password
});
},
/**
* Login with TOTP MFA.
*
* @param {string} username
* @param {string} password
* @param {string} token
* @returns {Promise<ApiResponse>}
* */
loginTOTP: async (username, password, token) => {
return await postJSON(this.getPath(`/user/login`), {
username,
password,
totp: token
});
},
/**
* Login with MFA recovery code.
*
* @param {string} username
* @param {string} password
* @param {string} recoveryCode
* @returns {Promise<ApiResponse>}
* */
loginMFARecoveryCode: async (username, password, recoveryCode) => {
return await postJSON(this.getPath(`/user/login`), {
username,
password,
totp: '',
recoveryCode: recoveryCode
});
},
/**
* Log out.
*
* @returns {Promise<ApiResponse>}
*/
logout: async () => {
return await postJSON(this.getPath(`/user/logout`));
},
/**
* Change the user's username
*
* @param {string} newUsername
* @returns {Promise<ApiResponse>}
*/
changeUsername: async (newUsername) => {
return await postJSON(this.getPath(`/user/username`), {
username: newUsername
});
},
/**
* Change the user's full name
*
* @param {string} newFullname
* @returns {Promise<ApiResponse>}
*/
changeFullname: async (newFullname) => {
return await postJSON(this.getPath(`/user/fullname`), {
fullname: newFullname
});
},
/**
* Change the user's password
*
* @param {string} currentPassword
* @param {string} newPassword
* @returns {Promise<ApiResponse>}
*/
changePassword: async (currentPassword, newPassword) => {
return await postJSON(this.getPath(`/user/password`), {
currentPassword,
newPassword
});
},
/**
*
* @param {string} password
* @returns {Promise<ApiResponse>}
*/
setupTOTPMFA: async (password) => {
return await postJSON(this.getPath(`/user/mfa/totp/setup`), {
password: password
});
},
/**
* Verify TOTP MFA setup
*
* @param {string} token
* @returns {Promise<ApiResponse>}
*/
setupVerifyTOTPMFA: async (token) => {
return await postJSON(this.getPath(`/user/mfa/totp/setup/verify`), {
token: token
});
},
/**
* Check if TOTP MFA is enabled
*
* @returns {Promise<ApiResponse>}
*/
isTOTPMFAEnabled: async () => {
return await getJSON(this.getPath(`/user/mfa/totp`));
},
/**
* Verify TOTP MFA
*
* @param {string} token
* @returns
*/
verifyTOTPMFA: async (token) => {
return await postJSON(this.getPath(`/user/mfa/totp/verify`), {
token: token
});
},
/**
* Disable TOTP MFA
* Requires the TOTP token to complete
*
* @param {string} totpToken
* @returns
*/
disableTOTPMFA: async (totpToken = '') => {
return await postJSON(this.getPath(`/user/mfa/totp`), {
token: totpToken
});
},
/**
* Disable TOTP MFA
* Requires the TOTP token to complete
*
* @param {string} userID
* @returns
*/
invalidateSessions: async (userID = '') => {
if (userID) {
return await postJSON(this.getPath(`/user/sessions/invalidate`), { userID });
}
const res = await fetch(this.getPath(`/user/sessions/invalidate`), {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
let body = {};
try {
body = await res.json();
} catch (e) {
body = {
success: false,
error: 'invalid JSON in response'
};
}
return newResponse(body.success, res.status, body.error, body.data);
}
};
/**
* option is the API settings.
*/
option = {
/**
* Get setting by key.
*
* @param {'is_installed'|'max_file_upload_size_mb'|'repeat_offender_months'|'sso_login'|'display_mode'|'obfuscation_template'} key
* @returns {Promise<ApiResponse>}
*/
get: async (key) => {
return await getJSON(this.getPath(`/option/${key}`));
},
/**
* Get the global auto-prune orphaned recipients setting.
* Returns the full option including per-company entries.
*
* @returns {Promise<ApiResponse>}
*/
getAutoPrune: async () => {
return await getJSON(this.getPath(`/option/auto-prune`));
},
/**
* Set the global auto-prune orphaned recipients setting.
* The full option object (including per-company entries) must be supplied.
*
* @param {{ enabled: boolean, companies?: string[] }} option
* @returns {Promise<ApiResponse>}
*/
setAutoPrune: async (option) => {
return await postJSON(this.getPath(`/option/auto-prune`), option);
},
/**
* Set setting by key and value.
*
* @param {'max_file_upload_size_mb'|'repeat_offender_months'|'sso_login'|'display_mode'|'obfuscation_template'} key
* @param {string} value
* @returns {Promise<ApiResponse>}
*/
set: async (key, value) => {
return await postJSON(this.getPath(`/option`), {
key: key,
value: value
});
}
};
/**
* log is the API for log related operations.
*/
recipient = {
/**
* Get all recipients using pagination.
*
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
countRepeatOffenders: async (companyID = null) => {
return await getJSON(
this.getPath(
`/recipient/repeat-offenders?${appendQuery(null)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get all recipients using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/recipient?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get all orphaned recipients (recipients not in any group) using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getOrphaned: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/recipient/orphaned?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Delete all orphaned recipients (recipients not in any group).
*
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
deleteAllOrphaned: async (companyID = null) => {
return await deleteReq(
this.getPath(`/recipient/orphaned/delete?${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get campaign events related by recipient id and optional campaign id
*
* @param {string} recipientID
* @param {TableURLParams} options
* @param {string} [campaignID]
* @returns {Promise<ApiResponse>}
*/
getEvents: async (recipientID, options, campaignID) => {
let path = `/recipient/${recipientID}/events?${appendQuery(options)}`;
if (campaignID) {
path += `&campaignID=${campaignID}`;
}
return await getJSON(this.getPath(path));
},
/**
* Get a recipient stats by ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getStatsByID: async (id) => {
return await getJSON(this.getPath(`/recipient/${id}/stats`));
},
/**
* Get a recipient by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/recipient/${id}`));
},
/**
* Update a recipient.
*
* @param {object} recipient
* @param {string} recipient.id
* @param {string} recipient.email
* @param {string} recipient.phone
* @param {string} recipient.extraIdentifier
* @param {string} recipient.firstName
* @param {string} recipient.lastName
* @param {string} recipient.position
* @param {string} recipient.department
* @param {string} recipient.city
* @param {string} recipient.country
* @param {string} recipient.misc
* @param {string} recipient.companyID
* @returns {Promise<ApiResponse>}
*/
update: async ({
id,
email,
phone,
extraIdentifier,
firstName,
lastName,
position,
department,
city,
country,
misc,
companyID
}) => {
return await patchJSON(this.getPath(`/recipient/${id}`), {
email: email,
phone: phone,
extraIdentifier: extraIdentifier,
firstName: firstName,
lastName: lastName,
position: position,
department: department,
city: city,
country: country,
misc: misc,
companyID: companyID
});
},
/**
* Create a new recipient.
*
* @param {object} recipient
* @param {string} recipient.email
* @param {string} recipient.phone
* @param {string} recipient.extraIdentifier
* @param {string} recipient.firstName
* @param {string} recipient.lastName
* @param {string} recipient.position
* @param {string} recipient.department
* @param {string} recipient.city
* @param {string} recipient.country
* @param {string} recipient.misc
* @param {string} recipient.companyID
* @returns {Promise<ApiResponse>}
*/
create: async ({
email,
phone,
extraIdentifier,
firstName,
lastName,
position,
department,
city,
country,
misc,
companyID
}) => {
return await postJSON(this.getPath('/recipient/'), {
email: email,
phone: phone,
extraIdentifier: extraIdentifier,
firstName: firstName,
lastName: lastName,
position: position,
department: department,
city: city,
country: country,
misc: misc,
companyID: companyID
});
},
/**
* Delete a recipient.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/recipient/${id}`));
},
/**
* Create a new recipient group.
*
* @param {string} name
* @param {string} companyID
* @param {Object[]} recipients // TODO define type for recipient
* @returns {Promise<ApiResponse>}
*/
createGroup: async (name, companyID, recipients) => {
return await postJSON(this.getPath('/recipient/group'), {
name: name,
companyID: companyID,
recipients: recipients ?? []
});
},
/**
* Create a dynamic recipient group.
*
* @param {string} name
* @param {string|null} companyID
* @param {string} filterField - recipient attribute to filter on (position, department, city, country, misc)
* @param {string} filterValue - value to match against the filter field
* @returns {Promise<ApiResponse>}
*/
createDynamicGroup: async (name, companyID, filterField, filterValue) => {
return await postJSON(this.getPath('/recipient/group'), {
name: name,
companyID: companyID,
isDynamic: true,
filterField: filterField,
filterValue: filterValue
});
},
/**
* Update a recipient group - not the recipients in the group.
*
* @param {object} group
* @param {string} group.id
* @param {string} [group.name ]
* @param {string} [group.companyID]
* @returns {Promise<ApiResponse>}
*/
updateGroup: async ({ id, name, companyID }) => {
return await patchJSON(this.getPath(`/recipient/group/${id}`), {
name: name,
companyID: companyID
});
},
/**
* Update a dynamic recipient group.
*
* @param {object} group
* @param {string} group.id
* @param {string} [group.name]
* @param {string} [group.filterField]
* @param {string} [group.filterValue]
* @returns {Promise<ApiResponse>}
*/
updateDynamicGroup: async ({ id, name, filterField, filterValue }) => {
return await patchJSON(this.getPath(`/recipient/group/${id}`), {
name: name,
isDynamic: true,
filterField: filterField,
filterValue: filterValue
});
},
/**
* Get all recipient groups using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllGroups: async (options, companyID) => {
return await getJSON(
this.getPath(
`/recipient/group?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get all recipients in a group using pagination.
*
* @param {string} id
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getAllByGroupID: async (id, options) => {
return await getJSON(
this.getPath(`/recipient/group/${id}/recipients?${appendQuery(options)}`)
);
},
/**
* Get a recipient group by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getGroupByID: async (id) => {
return await getJSON(this.getPath(`/recipient/group/${id}`));
},
/**
* Import recipients.
*
* @param {Object} import
* @param {Object[]} import.recipients // TODO define type for recipients
* @param {string} import.companyID
* @param {boolean} import.ignoreOverwriteEmptyFields existing recipient data for empty fields
* @returns {Promise<ApiResponse>}
*/
import: async ({ recipients, companyID, ignoreOverwriteEmptyFields = false }) => {
return await postJSON(this.getPath(`/recipient/import`), {
recipients: recipients,
ignoreOverwriteEmptyFields: ignoreOverwriteEmptyFields,
companyID: companyID
});
},
/**
* Import recipients to a group.
*
* @param {Object} import
* @param {Object[]} import.recipients // TODO define type for recipients
* @param {string} import.groupID
* @param {string} import.companyID
* @param {boolean} import.ignoreOverwriteEmptyFields existing recipient data for empty fields
* @returns {Promise<ApiResponse>}
*/
importToGroup: async ({
recipients,
groupID,
companyID,
ignoreOverwriteEmptyFields = false
}) => {
return await putJSON(this.getPath(`/recipient/group/${groupID}/import`), {
recipients: recipients,
ignoreOverwriteEmptyFields: ignoreOverwriteEmptyFields,
companyID: companyID
});
},
/**
* @param {string} recipientID
* @returns
*/
export: async (recipientID) => {
window.open(this.getPath(`/recipient/${recipientID}/export`), '_blank');
},
/**
* Add recipients to a group.
*
* @param {string} groupID
* @param {Object[]} recipients // TODO define type for recipients
* @returns {Promise<ApiResponse>}
*/
addToGroup: async (groupID, recipients) => {
return await postJSON(this.getPath(`/recipient/group/${groupID}/recipients`), {
recipientIDs: recipients
});
},
/**
* Remove recipients from a group.
*
* @param {string} groupID
* @param {*[]} recipients // TODO define type for recipients
* @returns {Promise<ApiResponse>}
*/
removeFromGroup: async (groupID, recipients) => {
return await deleteJSON(this.getPath(`/recipient/group/${groupID}/recipients`), {
recipientIDs: recipients
});
},
/**
* Delete a recipient group.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
deleteGroup: async (id) => {
return await deleteJSON(this.getPath(`/recipient/group/${id}`));
}
};
/**
* api sender is the API for the API sender related operations.
*
* @type {Object}
**/
apiSender = {
/**
* Create a new API sender.
*
* @param {Object} sender
* @param {string} sender.name
* @param {string} sender.apiKey
* @param {string} sender.companyID
* @param {string} sender.customField1
* @param {string} sender.customField2
* @param {string} sender.customField3
* @param {string} sender.customField4
* @param {string} sender.oauthProviderID
* @param {string} sender.requestMethod
* @param {string} sender.requestURL
* @param {APISenderHeader[]} sender.requestHeaders
* @param {string} sender.requestBody
* @param {string|number} sender.expectedResponseStatusCode
* @param {APISenderHeader[]} sender.expectedResponseHeaders
* @param {string} sender.expectedResponseBody
* @returns {Promise<ApiResponse>}
*/
create: async ({
name,
apiKey,
companyID,
customField1,
customField2,
customField3,
customField4,
oauthProviderID,
requestMethod,
requestURL,
requestHeaders,
requestBody,
expectedResponseStatusCode,
expectedResponseHeaders,
expectedResponseBody
}) => {
if (typeof expectedResponseStatusCode === 'string' && expectedResponseStatusCode.length > 0) {
expectedResponseStatusCode = parseInt(expectedResponseStatusCode);
} else {
expectedResponseStatusCode = null;
}
return await postJSON(this.getPath('/api-sender'), {
name: name,
apiKey: apiKey,
companyID: companyID,
customField1: customField1,
customField2: customField2,
customField3: customField3,
customField4: customField4,
oauthProviderID: oauthProviderID,
requestMethod: requestMethod,
requestURL: requestURL,
requestHeaders: requestHeaders,
requestBody: requestBody,
expectedResponseStatusCode: expectedResponseStatusCode,
expectedResponseHeaders: expectedResponseHeaders,
expectedResponseBody: expectedResponseBody
});
},
/**
* Update an API sender.
*
* @param {Object} sender
* @param {string} sender.id
* @param {string} sender.name
* @param {string} sender.apiKey
* @param {string} sender.companyID
* @param {string} sender.customField1
* @param {string} sender.customField2
* @param {string} sender.customField3
* @param {string} sender.customField4
* @param {string} sender.oauthProviderID
* @param {string} sender.requestMethod
* @param {string} sender.requestURL
* @param {APISenderHeader[]} sender.requestHeaders
* @param {string} sender.requestBody
* @param {string|number} sender.expectedResponseStatusCode
* @param {APISenderHeader[]} sender.expectedResponseHeaders
* @param {string} sender.expectedResponseBody
*/
update: async ({
id,
name,
apiKey,
companyID,
customField1,
customField2,
customField3,
customField4,
oauthProviderID,
requestMethod,
requestURL,
requestHeaders,
requestBody,
expectedResponseStatusCode,
expectedResponseHeaders,
expectedResponseBody
}) => {
if (typeof expectedResponseStatusCode === 'string' && expectedResponseStatusCode.length > 0) {
expectedResponseStatusCode = parseInt(expectedResponseStatusCode);
} else if (typeof expectedResponseStatusCode === 'number') {
// noop
} else {
expectedResponseStatusCode = null;
}
return await patchJSON(this.getPath(`/api-sender/${id}`), {
name: name,
apiKey: apiKey,
companyID: companyID,
customField1: customField1,
customField2: customField2,
customField3: customField3,
customField4: customField4,
oauthProviderID: oauthProviderID,
requestMethod: requestMethod,
requestURL: requestURL,
requestHeaders: requestHeaders,
requestBody: requestBody,
expectedResponseStatusCode: expectedResponseStatusCode,
expectedResponseHeaders: expectedResponseHeaders,
expectedResponseBody: expectedResponseBody
});
},
/**
* Get all API senders using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/api-sender?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get all overview API senders using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllOverview: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/api-sender/overview?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get an API sender by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/api-sender/${id}`));
},
/**
* Delete an API sender by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/api-sender/${id}`));
},
/**
* Send a test request to an API sender.
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
test: async (id) => {
return await postJSON(this.getPath(`/api-sender/${id}/test`));
}
};
/**
* log is the API for log related operations.
*/
allowDeny = {
/**
* Create a new allowdeny list.
*
* @param {Object} allowdeny
* @param {string} allowdeny.name
* @param {string} allowdeny.cidrs
* @param {string} allowdeny.ja4Fingerprints
* @param {string} allowdeny.countryCodes
* @param {string} allowdeny.headers
* @param {boolean} allowdeny.allowed
* @param {string} allowdeny.companyID
* @returns {Promise<ApiResponse>}
*/
create: async ({ name, cidrs, ja4Fingerprints, countryCodes, headers, allowed, companyID }) => {
return await postJSON(this.getPath('/allow-deny'), {
name: name,
cidrs: cidrs,
ja4Fingerprints: ja4Fingerprints,
countryCodes: countryCodes,
headers: headers,
allowed: allowed,
companyID: companyID
});
},
/**
* GetAll allowdeny list.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/allow-deny?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* GetAllOverview gets allowdeny list without cidrs.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllOverview: async (options, companyID = null) => {
return await getJSON(
this.getPath(
`/allow-deny/overview?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`
)
);
},
/**
* Get an allowdeny list by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/allow-deny/${id}`));
},
/**
* Update an allowdeny list.
*
* @param {Object} allowdeny
* @param {string} allowdeny.id
* @param {string} allowdeny.name
* @param {string} allowdeny.cidrs
* @param {string} allowdeny.ja4Fingerprints
* @param {string} allowdeny.countryCodes
* @param {string} allowdeny.headers
* @param {string} allowdeny.companyID
* @returns {Promise<ApiResponse>}
*/
update: async ({ id, name, cidrs, ja4Fingerprints, countryCodes, headers, companyID }) => {
return await patchJSON(this.getPath(`/allow-deny/${id}`), {
name: name,
cidrs: cidrs,
ja4Fingerprints: ja4Fingerprints,
countryCodes: countryCodes,
headers: headers,
companyID: companyID
});
},
/**
* Delete an allowdeny list by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/allow-deny/${id}`));
}
};
/**
* geoip is the API for GeoIP related operations.
*/
geoip = {
/**
* Get GeoIP metadata including available country codes.
*
* @returns {Promise<ApiResponse>}
*/
getMetadata: async () => {
return await getJSON(this.getPath('/geoip/metadata'));
}
};
/**
* webhook is the API for web hook related operations.
*/
webhook = {
/**
* Create a new webhook.
*
* @param {Object} webhook
* @param {string} webhook.name
* @param {string} webhook.url
* @param {string} [webhook.secret]
* @param {string} [webhook.companyID]
* @returns {Promise<ApiResponse>}
*/
create: async ({ name, url, secret, companyID }) => {
return await postJSON(this.getPath('/webhook'), {
name: name,
url: url,
secret: secret,
companyID: companyID
});
},
/**
* GetAll webhooks.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/webhook?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get a webhook by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/webhook/${id}`));
},
/**
* Update a webhook.
*
* @param {Object} webhook
* @param {string} webhook.id
* @param {string} webhook.name
* @param {string} webhook.url
* @param {string} webhook.secret
* @param {string} webhook.companyID
* @returns {Promise<ApiResponse>}
*/
update: async ({ id, name, url, secret, companyID }) => {
return await patchJSON(this.getPath(`/webhook/${id}`), {
name: name,
url: url,
secret: secret,
companyID: companyID
});
},
/**
* Delete a webhook by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/webhook/${id}`));
},
/**
* Test a webhook.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
test: async (id) => {
return await postJSON(this.getPath(`/webhook/${id}/test`));
}
};
/**
* identifier is for campaign identifiers, ala. 'rid' in gophish
*/
identifier = {
/**
* @param {TableURLParams} options
* @returns {Promise<ApiResponse>}
*/
getAll: async (options) => {
return await getJSON(this.getPath(`/identifier?${appendQuery(options)}`));
}
};
/**
* sso is for handling sso configuration
*/
sso = {
/**
* @param {object} sso
* @param {string} sso.clientID
* @param {string} sso.tenantID
* @param {string} sso.clientSecret
* @param {string} sso.redirectURL
* @returns {Promise<ApiResponse>}
*/
upsert: async (sso) => {
return await postJSON(this.getPath(`/sso/entra-id`), sso);
},
isEnabled: async () => {
return await getJSON(this.getPath(`/sso/entra-id/enabled`));
}
};
/**
* utils is for useful utils
*/
utils = {
/**
* @param {object} qr
* @param {string} qr.url
* @param {number} qr.dotSize
* @returns {Promise<ApiResponse>}
*/
qr: async (qr) => {
return await postJSON(this.getPath(`/qr/html`), qr);
}
};
version = {
/**
* @returns {Promise<ApiResponse>}
*/
get: async () => {
return await getJSON(this.getPath(`/version`));
}
};
/**
* proxy is the API for Proxy related operations.
*/
proxy = {
/**
* Get a Proxy by its ID.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
getByID: async (id) => {
return await getJSON(this.getPath(`/proxy/${id}`));
},
/**
* Get all Proxies using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAll: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/proxy?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Get all Proxies overview using pagination.
*
* @param {TableURLParams} options
* @param {string|null} companyID
* @returns {Promise<ApiResponse>}
*/
getAllSubset: async (options, companyID = null) => {
return await getJSON(
this.getPath(`/proxy/overview?${appendQuery(options)}${this.appendCompanyQuery(companyID)}`)
);
},
/**
* Create a new Proxy.
*
* @param {object} proxy
* @param {string} proxy.name
* @param {string} proxy.description
* @param {string} proxy.startURL
* @param {string} proxy.proxyConfig
* @param {string} proxy.companyID
* @param {string} [proxy.globalTLSKey]
* @param {string} [proxy.globalTLSPem]
* @returns {Promise<ApiResponse>}
*/
create: async ({
name,
description,
startURL,
proxyConfig,
companyID,
globalTLSKey,
globalTLSPem
}) => {
return await postJSON(this.getPath('/proxy'), {
name: name,
description: description,
startURL: startURL,
proxyConfig: proxyConfig,
companyID: companyID,
...(globalTLSKey ? { globalTLSKey } : {}),
...(globalTLSPem ? { globalTLSPem } : {})
});
},
/**
* Update a Proxy.
*
* @param {string} id
* @param {object} proxy
* @param {string} proxy.name
* @param {string} proxy.description
* @param {string} proxy.startURL
* @param {string} proxy.proxyConfig
* @param {string} [proxy.globalTLSKey]
* @param {string} [proxy.globalTLSPem]
* @returns {Promise<ApiResponse>}
*/
update: async (id, proxy) => {
return await patchJSON(this.getPath(`/proxy/${id}`), proxy);
},
/**
* Delete a Proxy.
*
* @param {string} id
* @returns {Promise<ApiResponse>}
*/
delete: async (id) => {
return await deleteJSON(this.getPath(`/proxy/${id}`));
}
};
/**
* ipAllowList is the API for IP Allow List related operations.
*/
ipAllowList = {
/**
* Get IP allow list entries for a specific proxy configuration.
*
* @param {string} proxyConfigID
* @returns {Promise<ApiResponse>}
*/
getForProxyConfig: async (proxyConfigID) => {
return await getJSON(this.getPath(`/ip-allow-list/proxy-config/${proxyConfigID}`));
},
/**
* Clear all entries for a specific proxy configuration.
*
* @param {string} proxyConfigID
* @returns {Promise<ApiResponse>}
*/
clearForProxyConfig: async (proxyConfigID) => {
return await deleteJSON(this.getPath(`/ip-allow-list/clear-proxy-config/${proxyConfigID}`));
}
};
/**
* import is for importing assets, landing pages and etc
*/
import = {
import: async (fileOrFormData) => {
if (fileOrFormData instanceof FormData) {
return await postMultipart(this.getPath('/import'), fileOrFormData);
} else if (fileOrFormData) {
const formData = new FormData();
formData.append('file', fileOrFormData);
return await postMultipart(this.getPath('/import'), formData);
}
}
};
}