ro
c5afbb9131
removed all remaining API requests from the front end and removed the FipamoAdminAPI js file, changing it to ContentRequest as it now handles posting data to the system directly, authenticating it self by checking the embedded CSRF token that regulary rotates also renamed MaintenanceManager to Maintenance request and moved it to the same dir as ContentRequest as they are both libraries that connect to the backend
417 lines
12 KiB
JavaScript
417 lines
12 KiB
JavaScript
//** REQUEST TYPES **//
|
|
export const REQUEST_TYPE_POST = 'POST';
|
|
export const REQUEST_TYPE_GET = 'GET';
|
|
export const REQUEST_TYPE_PUT = 'PUT';
|
|
export const REQUEST_TYPE_DELETE = 'DELETE';
|
|
//** POST CONTENT TYPES **//
|
|
export const CONTENT_TYPE_JSON = 'json';
|
|
export const CONTENT_TYPE_FORM = 'x-www-form-urlencoded';
|
|
//** ACTIONS URLS **//
|
|
export const API_NEW_PAGE = '/page/create';
|
|
export const API_EDIT_PAGE = '/page/write';
|
|
export const API_DELETE_PAGE = '/page/delete';
|
|
export const API_GET_SETTINGS = '/settings/site';
|
|
export const API_SETTINGS_SYNC = '/settings/sync';
|
|
export const API_PUBLISH_PAGES = '/settings/publish';
|
|
export const API_NAV_SYNC = '/settings/nav-sync';
|
|
|
|
export const API_GET_MEMBER_INFO = '/settings/member';
|
|
export const API_REINDEX_PAGES = '/settings/reindex';
|
|
export const API_SEND_MAIL = '/settings/mailer';
|
|
|
|
export const API_LOGIN = '/login';
|
|
//** ACTIONS TASKS **//
|
|
export const AUTH_STATUS = 'getAuthStatus';
|
|
export const TASK_SETTINGS_WRITE = 'writeSettings';
|
|
export const TASK_PUBLISH_SITE = 'publishSite';
|
|
export const TASK_PAGE_CREATE = 'createNewPage';
|
|
export const TASK_PAGE_EDIT = 'editPage';
|
|
export const TASK_PAGE_DELETE = 'deletePage';
|
|
export const TASK_SEND_MAIL = 'sendMail';
|
|
export const TASK_REINDEX_PAGE = 'reIndexPages';
|
|
export const TASK_SYNC_SETTNIGS = 'syncSite';
|
|
export const TASK_SYNC_NAV = 'syncNav';
|
|
export const TASK_GET_SETTINGS = 'getSiteSettings';
|
|
export const TASK_GET_MEMBER_INFO = 'getMemberInfo';
|
|
//** ACTIONS STATUS **//
|
|
export const API_ACCESS_GOOD = 'apiUseAuthorized';
|
|
export const API_ACCESS_BAD = 'apiUseNotAuthorized';
|
|
|
|
/**
|
|
* A can of methods used to edit install settings, navigation pages and content pages
|
|
*/
|
|
|
|
class ContentRequest {
|
|
/**
|
|
* @constructor
|
|
* @param {string} baseURL - url of site; uses local when empty
|
|
* @param {object} progressBar - element to be used to display upload progress
|
|
*/
|
|
constructor(baseURL = null, progressBar = null) {
|
|
this.percentComplete = 0; //for later
|
|
this.baseURL = null;
|
|
this.progressBar = progressBar;
|
|
this.status = false;
|
|
if (baseURL) this.baseURL = baseURL;
|
|
}
|
|
/**
|
|
* Promise method for authenticating and starting a session\
|
|
* **POST**`/api/v1/login`
|
|
* @param {Object[]} data - json object that contains data for set up
|
|
* @param {string} data[].handle - handle for site user
|
|
* @param {string} data[].password - password for site user
|
|
* @example
|
|
* api.login(data).then(response=>{
|
|
* console.log("RESPONSE", response);
|
|
* })
|
|
* @returns {object} json object that contains type and status of login request
|
|
```
|
|
{
|
|
"message":"Example Message of Affirmation or what you're missing!",
|
|
"type":"exampleType",
|
|
}
|
|
```
|
|
*/
|
|
login(data) {
|
|
return new Promise((resolve, reject) => {
|
|
this.baseURL ? (data.remote = true) : (data.remote = false);
|
|
this.key ? (data.key = this.key) : (data.key = null);
|
|
this._request(
|
|
this.baseURL ? this.baseURL + API_LOGIN : API_LOGIN,
|
|
AUTH_STATUS,
|
|
REQUEST_TYPE_POST,
|
|
CONTENT_TYPE_JSON,
|
|
data
|
|
)
|
|
.then(result => {
|
|
resolve(result);
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* Method for saving site and navigation settings\
|
|
* **POST**`/api/v1/settings/:task`
|
|
* @param {string} task - settings being synced `config | navigation`
|
|
* @param {object[]} data - json object that contains settings data for [site] or [nav]
|
|
* @param {string} data[].global.base_url - base url for site [site]
|
|
* @param {string} data[].global.title - site title [site]
|
|
* @param {string} data[].global.descriptions - brief site summary [site]
|
|
* @param {string} data[].global.background - url for site feature image for header [site]
|
|
* @param {boolean} data[].global.private - privacy state for site [disabled] [site]
|
|
* @param {boolean} data[].global.renderOnSave - property for publishing site when page saved [disabled] [site]
|
|
* @param {string} data[].global.theme - current theme for site [site]
|
|
* @param {boolean} data[].global.externalAPI - toggle for external API access [site]
|
|
* @param {string} data[].member.handle - current member handle [site]
|
|
* @param {string} data[].member.email - current member email [site]
|
|
* @param {string} data[].email.active - current email protocol being used [site]
|
|
* @param {string} data[].email.smtp.domain - url of smtp service being [site]
|
|
* @param {string} data[].email.smtp.email - email account of smtp service [site]
|
|
* @param {string} data[].email.smtp.password - password for email of smtp service [site]
|
|
* @param {string} data[].email.mailgun.domain - mailgun domain url [site]
|
|
* @param {string} data[].email.mailgun.key - mailgun key [site]
|
|
*
|
|
* @param {string} data[].item.title - page title [nav]
|
|
* @param {string} data[].item.slug - url safe title [nav]
|
|
* @param {string} data[].item.uuid - unique identifier [nav]
|
|
* @param {string} data[].item.path - directory path to associated markdown file [nav]
|
|
* @example
|
|
* api.sync(TASK, data).then(response=>{
|
|
* console.log("RESPONSE", response);
|
|
* })
|
|
* @returns {object} json object that contains type and status of sync request
|
|
```
|
|
*
|
|
{
|
|
"message":"Example Message of Affirmation!",
|
|
"type":"exampleType",
|
|
}
|
|
```
|
|
*/
|
|
sync(task, data) {
|
|
return new Promise((resolve, reject) => {
|
|
let url = '';
|
|
switch (task) {
|
|
case 'syncSite':
|
|
url = API_SETTINGS_SYNC;
|
|
break;
|
|
case 'syncNav':
|
|
url = API_NAV_SYNC;
|
|
break;
|
|
}
|
|
this._request(
|
|
this.baseURL ? this.baseURL + url : url,
|
|
TASK_SETTINGS_WRITE,
|
|
REQUEST_TYPE_PUT,
|
|
CONTENT_TYPE_JSON,
|
|
data
|
|
)
|
|
.then(result => {
|
|
resolve(result);
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Method for retrieving user authorizing user login
|
|
* @param {object[]} data - json object that contains task
|
|
* @param {string} data[].task - publishing task
|
|
* @example
|
|
* api.publish(TASK).then(response=>{
|
|
* console.log("RESPONSE", response);
|
|
* })
|
|
* @returns {object} json object that contains type and status of publis request
|
|
* ```
|
|
{
|
|
"message":"Example Message of Affirmation!",
|
|
"type":"exampleType",
|
|
}
|
|
* ```
|
|
*/
|
|
publish(data) {
|
|
return new Promise((resolve, reject) => {
|
|
this._request(
|
|
//API_PUBLISH_PAGES,
|
|
this.baseURL ? this.baseURL + API_PUBLISH_PAGES : API_PUBLISH_PAGES,
|
|
TASK_PUBLISH_SITE,
|
|
REQUEST_TYPE_PUT,
|
|
CONTENT_TYPE_JSON,
|
|
data
|
|
)
|
|
.then(result => {
|
|
resolve(result);
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Method for handling page creating and editing\
|
|
* **POST**`/api/v1/page/:task`
|
|
* @param {string} task - current page action
|
|
* @param {object[]} form - form object that contains info for current page being edited/created
|
|
* @param {string} form[].id - sequence id for page, leave empty for new page
|
|
* @param {string} form[].uuid - unique identifier for page, leave empty for new page
|
|
* @param {string} form[].layout - current page layout
|
|
* @param {string} form[].current_title - saved url save title for persistence when changing title, leave empty for new page
|
|
* @param {string} form[].content - markdown body of page
|
|
* @param {string} form[].title - current title of page
|
|
* @param {string} form[].created - date page was created, leave empty for new page
|
|
* @param {string} form[].slug - url safe string of page title
|
|
* @param {string} form[].tags - comma separated list of tags
|
|
* @param {boolean} form[].menu - property that indicates page is included in site menu
|
|
* @param {boolean} form[].featured - property that indicates page is featured
|
|
* @param {boolean} form[].published - property that indicates page is public
|
|
* @param {string} form[].form_token - hidden property to authenticate form submission
|
|
* @param {input} form[].feature_image - main image for page
|
|
* @example
|
|
* api.pageActions(TASK, data).then(response=>{
|
|
* console.log("RESPONSE", response);
|
|
* })
|
|
* @returns {object} json object that contains type and status of page edit request
|
|
```
|
|
{
|
|
"message":"Example Message of Affirmation!",
|
|
"type":"exampleType",
|
|
}
|
|
```
|
|
*/
|
|
pageActions(task, data) {
|
|
let url, event, content, type;
|
|
switch (task) {
|
|
case TASK_PAGE_CREATE:
|
|
url = API_NEW_PAGE;
|
|
event = TASK_PAGE_CREATE;
|
|
content = CONTENT_TYPE_JSON;
|
|
type = REQUEST_TYPE_POST;
|
|
break;
|
|
case TASK_PAGE_EDIT:
|
|
url = API_EDIT_PAGE;
|
|
event = TASK_PAGE_EDIT;
|
|
content = CONTENT_TYPE_JSON;
|
|
type = REQUEST_TYPE_PUT;
|
|
break;
|
|
|
|
case TASK_PAGE_DELETE:
|
|
url = API_DELETE_PAGE;
|
|
event = TASK_PAGE_DELETE;
|
|
content = CONTENT_TYPE_JSON;
|
|
type = REQUEST_TYPE_DELETE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
if (this.baseURL) {
|
|
//data.key = this.key;
|
|
data.remote = true;
|
|
} else {
|
|
data.remote = false;
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this._request(
|
|
this.baseURL ? this.baseURL + url : url,
|
|
event,
|
|
type,
|
|
content,
|
|
data
|
|
)
|
|
.then(result => {
|
|
resolve(result);
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Method for sending mail (if completed in settings)\
|
|
* **POST**`/api/v1/mailer`
|
|
* @param {object[]} message - json object that contains items to be included in main site navigation
|
|
* @param {string} message[].content - message to send
|
|
* @example
|
|
* api.sendMail(message).then(response=>{
|
|
* console.log("RESPONSE", response);
|
|
* })
|
|
* @returns {object} json object that contains type and status of page edit request
|
|
```
|
|
{
|
|
"message":"Example Message of Affirmation!",
|
|
"type":"exampleType"
|
|
}
|
|
```
|
|
*/
|
|
sendMail(message) {
|
|
return new Promise((resolve, reject) => {
|
|
this._request(
|
|
this.baseURL ? this.baseURL + API_SEND_MAIL : API_SEND_MAIL,
|
|
TASK_SEND_MAIL,
|
|
REQUEST_TYPE_POST,
|
|
CONTENT_TYPE_JSON,
|
|
message
|
|
)
|
|
.then(result => {
|
|
resolve(result);
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* *Promise method for retrieving site and member info*\
|
|
* **GET** `/api/v1/settings/:type`
|
|
* @param {string} type - type of info requested ['site'|'member'];
|
|
* @example
|
|
* api.getInfo("type").then(data=>{
|
|
console.log("Info Object", data);
|
|
* })
|
|
* @returns {object} json object that contains data for requested information
|
|
*
|
|
* *info object example*
|
|
* ```
|
|
{
|
|
"message":"message of affirmation!",
|
|
"task":"type of info request",
|
|
"data":json-data-object,
|
|
}
|
|
* ```
|
|
*/
|
|
|
|
getInfo(type) {
|
|
let url, task;
|
|
if (type == 'site') {
|
|
url = API_GET_SETTINGS;
|
|
task = TASK_GET_SETTINGS;
|
|
} else {
|
|
url = API_GET_MEMBER_INFO;
|
|
task = TASK_GET_MEMBER_INFO;
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
this._request(this.baseURL ? this.baseURL + url : url, task)
|
|
.then(result => {
|
|
resolve(result);
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
|
|
//--------------------------
|
|
// private
|
|
//--------------------------
|
|
_request(
|
|
requestURL,
|
|
eventType,
|
|
requestType = REQUEST_TYPE_GET,
|
|
contentType = CONTENT_TYPE_JSON,
|
|
requestData = null
|
|
) {
|
|
var self = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var request = new XMLHttpRequest();
|
|
request.upload.addEventListener('progress', e =>
|
|
self.handleLoadProgress(e, self.progressBar)
|
|
);
|
|
request.open(requestType, requestURL, true);
|
|
request.setRequestHeader(
|
|
'X-CSRF-TOKEN',
|
|
document.querySelector('meta[name="csrf-token"]').content
|
|
);
|
|
request.onload = () => {
|
|
if (request.status == 200) {
|
|
let response = JSON.parse(request['response']);
|
|
resolve(response);
|
|
} else {
|
|
let error = JSON.parse(request['response']);
|
|
reject(error);
|
|
}
|
|
};
|
|
if (
|
|
requestType == REQUEST_TYPE_PUT ||
|
|
requestType == REQUEST_TYPE_POST ||
|
|
requestType == REQUEST_TYPE_DELETE
|
|
) {
|
|
switch (contentType) {
|
|
case CONTENT_TYPE_JSON:
|
|
request.setRequestHeader(
|
|
'Content-type',
|
|
'application/' + contentType
|
|
);
|
|
request.send(JSON.stringify(requestData));
|
|
break;
|
|
case CONTENT_TYPE_FORM:
|
|
request.send(requestData);
|
|
break;
|
|
}
|
|
} else {
|
|
request.send();
|
|
}
|
|
});
|
|
}
|
|
|
|
//--------------------------
|
|
// event handlers
|
|
//--------------------------
|
|
handleLoadProgress(e, progressBar) {
|
|
let percent = Math.ceil((e.loaded / e.total) * 100);
|
|
//if a progress bar element is present, talk to it
|
|
if (progressBar != null) {
|
|
progressBar.style.width = percent + '%';
|
|
}
|
|
}
|
|
}
|
|
|
|
export { ContentRequest as default };
|