Replaced Moment with Carbon #84
8 changed files with 92 additions and 332 deletions
|
@ -62,3 +62,19 @@ function createAppKey()
|
||||||
{
|
{
|
||||||
return 'base64:' . base64_encode(Encrypter::generateKey(config('app.cipher')));
|
return 'base64:' . base64_encode(Encrypter::generateKey(config('app.cipher')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isHttps()
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] == 1)) ||
|
||||||
|
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') ||
|
||||||
|
(isset($_SERVER['HTTP_X_FORWARDED_SCHEME']) && strtolower($_SERVER['HTTP_X_FORWARDED_SCHEME']) === 'https') ||
|
||||||
|
(isset($_SERVER['HTTP_X_FORWARDED_SSL']) && ($_SERVER['HTTP_X_FORWARDED_SSL'] === 'on' || $_SERVER['HTTP_X_FORWARDED_SSL'] == 1)) ||
|
||||||
|
(isset($_SERVER['REQUEST_SCHEME']) && strtolower($_SERVER['REQUEST_SCHEME']) === 'https') ||
|
||||||
|
(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,10 @@ class PageAPIController extends Controller
|
||||||
|
|
||||||
public function write(Request $request)
|
public function write(Request $request)
|
||||||
{
|
{
|
||||||
$body = json_decode($request->getContent());
|
$body = json_decode($request->getContent());
|
||||||
$result = $this->pages->update($body);
|
dd($body);
|
||||||
return response()->json($result)->header('Content-Type', 'application/json');
|
//$result = $this->pages->update($body);
|
||||||
|
//return response()->json($result)->header('Content-Type', 'application/json');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
|
|
|
@ -70,6 +70,6 @@ class Kernel extends HttpKernel
|
||||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||||
'member.check' => \App\Http\Middleware\MemberCheck::class,
|
'member.check' => \App\Http\Middleware\MemberCheck::class,
|
||||||
'validate.token' => \App\Http\Middleware\ValidateAPIToken::class,
|
'validate.key' => \App\Http\Middleware\ValidateAPIKey::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
66
app/Http/Middleware/ValidateAPIKey.php
Normal file
66
app/Http/Middleware/ValidateAPIKey.php
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use App\Interfaces\MemberRepositoryInterface;
|
||||||
|
use App\Services\Data\SettingsService;
|
||||||
|
|
||||||
|
use function _\find;
|
||||||
|
|
||||||
|
class ValidateAPIKey
|
||||||
|
{
|
||||||
|
protected $member;
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
MemberRepositoryInterface $memberRepo,
|
||||||
|
SettingsService $settingsService,
|
||||||
|
) {
|
||||||
|
$this->member = $memberRepo;
|
||||||
|
$this->settings = $settingsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
$response = [];
|
||||||
|
//checks to see if request is secure
|
||||||
|
if (isHttps()) {
|
||||||
|
$key = $request->header('fipamo-api-key');
|
||||||
|
$folks = $this->member->getAll();
|
||||||
|
//looks to see if API key exists
|
||||||
|
if (find($folks, ['key' => $key])) {
|
||||||
|
//final check to see if API requests are being accepted
|
||||||
|
$global = $this->settings->getGlobal();
|
||||||
|
if (isset($global['externalAPI']) && $global['externalAPI'] == "true") {
|
||||||
|
return $next($request);
|
||||||
|
} else {
|
||||||
|
$response = [
|
||||||
|
'message' => "API Auth Fail: Not Accepting Requests",
|
||||||
|
'type' => 'postError',
|
||||||
|
];
|
||||||
|
return response()->json($response)->header('Content-Type', 'application/json');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response = [
|
||||||
|
'message' => "API Auth Fail: API Key Invalid",
|
||||||
|
'type' => 'postError',
|
||||||
|
];
|
||||||
|
return response()->json($response)->header('Content-Type', 'application/json');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response = [
|
||||||
|
'message' => "API Auth Fail: Request must be secure (HTTPS)",
|
||||||
|
'type' => 'postError',
|
||||||
|
];
|
||||||
|
return response()->json($response)->header('Content-Type', 'application/json');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
|
|
||||||
class ValidateAPIToken
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
|
||||||
*/
|
|
||||||
public function handle(Request $request, Closure $next): Response
|
|
||||||
{
|
|
||||||
$token = $request->header('fipamo-access-token');
|
|
||||||
if ($token == session('token')) {
|
|
||||||
return $next($request);
|
|
||||||
} else {
|
|
||||||
$response = [
|
|
||||||
'message' => "API Auth Fail",
|
|
||||||
'type' => 'postError',
|
|
||||||
];
|
|
||||||
return response()->json($response)->header('Content-Type', 'application/json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,7 +27,7 @@ class MemberRepository implements MemberRepositoryInterface
|
||||||
|
|
||||||
public function getAll()
|
public function getAll()
|
||||||
{
|
{
|
||||||
return $this->$folks;
|
return $this->folks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getById($id)
|
public function getById($id)
|
||||||
|
|
|
@ -1,294 +0,0 @@
|
||||||
//** 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";
|
|
||||||
|
|
||||||
//** API URLS **//
|
|
||||||
export const API_GET_PAGES = "/api/v1/page/published";
|
|
||||||
export const API_GET_FEATURED = "/api/v1/page/featured";
|
|
||||||
export const API_GET_PAGE = "/api/v1/page/single";
|
|
||||||
export const API_GET_MENU = "/api/v1/page/menu";
|
|
||||||
export const API_GET_TAGS = "/api/v1/page/tags";
|
|
||||||
|
|
||||||
//** API TASKS **//
|
|
||||||
export const TASK_GET_CONTENT = "retrieveContent";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A bag of methods for getting content from an install.
|
|
||||||
*/
|
|
||||||
class FipamoContentAPI {
|
|
||||||
/**
|
|
||||||
* @constructor
|
|
||||||
* @param {string} baseURL - url of install, defaults to local
|
|
||||||
* @param {string} key - user api key found in Settings
|
|
||||||
* @author Ro
|
|
||||||
*/
|
|
||||||
constructor(baseURL = null, key = null) {
|
|
||||||
this.baseURL = null;
|
|
||||||
this.key = null;
|
|
||||||
if (key) this.key = key;
|
|
||||||
if (baseURL) this.baseURL = baseURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* *Promise method for retrieving page data*\
|
|
||||||
* **GET**`/api/v1/page/:type`
|
|
||||||
* @param {string} type - type of pages (`published | menu | featured`) being retrieved; null value defaults to `published`
|
|
||||||
* @example
|
|
||||||
* api.pages('published').then(pages=>{
|
|
||||||
* console.log("Pages Object", pages);
|
|
||||||
* })
|
|
||||||
* @returns {object} json object that contains pages of requested type
|
|
||||||
*
|
|
||||||
* *pages object example*
|
|
||||||
* ```
|
|
||||||
{
|
|
||||||
"pages":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id":1,
|
|
||||||
"uuid":"uuid-for-entry",
|
|
||||||
"title":"Entry Title",
|
|
||||||
"feature":"/path/to/image.jpg",
|
|
||||||
"path":"2020/09",
|
|
||||||
"layout":"page",
|
|
||||||
"tags":"these, are, tags",
|
|
||||||
"author":"your-name",
|
|
||||||
"created":"2020 Sep Tue 01",
|
|
||||||
"updated":"2020 Sep Tue 01",
|
|
||||||
"deleted":false,
|
|
||||||
"menu":false,
|
|
||||||
"featured":false,
|
|
||||||
"published":true,
|
|
||||||
"slug":"entry-title",
|
|
||||||
"content":"Premium Content"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":2,
|
|
||||||
"uuid":"uuid-for-entry",
|
|
||||||
"title":"Another Title",
|
|
||||||
"feature":"/path/to/image.jpg",
|
|
||||||
"path":"2020/09",
|
|
||||||
"layout":"page",
|
|
||||||
"tags":"these, are, tags",
|
|
||||||
"author":"your-name",
|
|
||||||
"created":"2020 Sep Tue 01",
|
|
||||||
"updated":"2020 Sep Tue 01",
|
|
||||||
"deleted":false,
|
|
||||||
"menu":false,
|
|
||||||
"featured":false,
|
|
||||||
"published":true,
|
|
||||||
"slug":"another-title",
|
|
||||||
"content":"Premium Content"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"totalItems":2
|
|
||||||
}
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
pages(type = null) {
|
|
||||||
//set url based on request type
|
|
||||||
let requestURL = "";
|
|
||||||
switch (type) {
|
|
||||||
default:
|
|
||||||
case "published":
|
|
||||||
requestURL = API_GET_PAGES + "?key=" + this.key;
|
|
||||||
break;
|
|
||||||
case "featured":
|
|
||||||
requestURL = API_GET_FEATURED + "?key=" + this.key;
|
|
||||||
break;
|
|
||||||
case "menu":
|
|
||||||
requestURL = API_GET_MENU + "?key=" + this.key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this._request(
|
|
||||||
this.baseURL ? this.baseURL + requestURL : requestURL,
|
|
||||||
TASK_GET_CONTENT
|
|
||||||
)
|
|
||||||
.then((result) => {
|
|
||||||
resolve(result);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* *Promise method for retrieving single page*\
|
|
||||||
* **GET** `/api/v1/page/single/:id`
|
|
||||||
* @param {string} id - uuid of desired page
|
|
||||||
* @example
|
|
||||||
* api.page("a-uuid-for-a-page").then(page=>{
|
|
||||||
console.log("Page Object", page);
|
|
||||||
* })
|
|
||||||
* @returns {object} json object that contains data for requested page
|
|
||||||
*
|
|
||||||
* *page object example*
|
|
||||||
* ```
|
|
||||||
{
|
|
||||||
"id":1,
|
|
||||||
"uuid":"uuid-for-entry",
|
|
||||||
"title":"Entry Title",
|
|
||||||
"feature":"/path/to/image.jpg",
|
|
||||||
"path":"2020/09",
|
|
||||||
"layout":"page",
|
|
||||||
"tags":"these, are, tags",
|
|
||||||
"author":"your-name",
|
|
||||||
"created":"2020 Sep Tue 01",
|
|
||||||
"updated":"2020 Sep Tue 01",
|
|
||||||
"deleted":false,
|
|
||||||
"menu":false,
|
|
||||||
"featured":false,
|
|
||||||
"published":true,
|
|
||||||
"slug":"entry-title",
|
|
||||||
"content":"Premium Content"
|
|
||||||
}
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
page(id) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this._request(
|
|
||||||
this.baseURL
|
|
||||||
? this.baseURL + API_GET_PAGE + "/" + id + "?key=" + this.key
|
|
||||||
: API_GET_PAGE + "/" + id + "?key=" + this.key,
|
|
||||||
TASK_GET_CONTENT,
|
|
||||||
REQUEST_TYPE_GET
|
|
||||||
)
|
|
||||||
.then((result) => {
|
|
||||||
resolve(result);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* *Promise method for retrieving all tags used by pages*\
|
|
||||||
* **GET** `/api/v1/page/tags`
|
|
||||||
* @example
|
|
||||||
* api.tags().then(tags=>{
|
|
||||||
console.log("Tags Object", tags);
|
|
||||||
* })
|
|
||||||
* @returns {object} json object that contains site tags and page stubs associated with said tag
|
|
||||||
*
|
|
||||||
* *tags object example*
|
|
||||||
* ```
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"tag_name":"this is a tag",
|
|
||||||
"slug":"this-is-a-tag",
|
|
||||||
"pages":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"title":"This is a title",
|
|
||||||
"slug":"this-is-a-title",
|
|
||||||
"path":"2021/04"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"title":"This is another title",
|
|
||||||
"slug":"this-is-another-title",
|
|
||||||
"path":"2020/10"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag_name":"this is another tag",
|
|
||||||
"slug":"this-is-another-tag",
|
|
||||||
"pages":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"title":"This is a title",
|
|
||||||
"slug":"this-is-a-title",
|
|
||||||
"path":"2021/04"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"title":"This is another title",
|
|
||||||
"slug":"this-is-another-title",
|
|
||||||
"path":"2020/10"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
tags() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this._request(
|
|
||||||
this.baseURL
|
|
||||||
? this.baseURL + API_GET_TAGS + "?key=" + this.key
|
|
||||||
: API_GET_TAGS + "?key=" + this.key,
|
|
||||||
TASK_GET_CONTENT,
|
|
||||||
REQUEST_TYPE_GET
|
|
||||||
)
|
|
||||||
.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.onprogress = self.handleLoadProgress;
|
|
||||||
request.open(requestType, requestURL, true);
|
|
||||||
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) {
|
|
||||||
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) {
|
|
||||||
this.percentComplete = Math.ceil((e.loaded / e.total) * 100);
|
|
||||||
//pass element to display request progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { FipamoContentAPI as default };
|
|
|
@ -23,27 +23,27 @@ Route::post("/v1/init", [InitAPIController::class, 'setupFresh']);
|
||||||
Route::post("/v1/restore", [InitAPIController::class, 'setupRestore']);
|
Route::post("/v1/restore", [InitAPIController::class, 'setupRestore']);
|
||||||
|
|
||||||
//handle page editing actions
|
//handle page editing actions
|
||||||
Route::group(['prefix' => '/v1/page', 'middleware' => 'validate.token'], function () {
|
Route::group(['prefix' => '/v1/page', 'middleware' => 'validate.key'], function () {
|
||||||
Route::put("/write", [PageAPIController::class, 'write']);
|
Route::put("/write", [PageAPIController::class, 'write']);
|
||||||
Route::post("/create", [PageAPIController::class, 'create']);
|
Route::post("/create", [PageAPIController::class, 'create']);
|
||||||
Route::delete("/delete", [PageAPIController::class, 'delete']);
|
Route::delete("/delete", [PageAPIController::class, 'delete']);
|
||||||
});
|
});
|
||||||
|
|
||||||
//settings
|
//settings
|
||||||
Route::group(['prefix' => '/v1/settings', 'middleware' => 'validate.token'], function () {
|
Route::group(['prefix' => '/v1/settings', 'middleware' => 'validate.key'], function () {
|
||||||
Route::put("/publish", [SettingsAPIController::class, 'publish']);
|
Route::put("/publish", [SettingsAPIController::class, 'publish']);
|
||||||
Route::put("/sync", [SettingsAPIController::class, 'sync']);
|
Route::put("/sync", [SettingsAPIController::class, 'sync']);
|
||||||
Route::put("/nav-sync", [SettingsAPIController::class, 'navSync']);
|
Route::put("/nav-sync", [SettingsAPIController::class, 'navSync']);
|
||||||
});
|
});
|
||||||
//backups
|
//backups
|
||||||
Route::group(['prefix' => '/v1/backup', 'middleware' => 'validate.token'], function () {
|
Route::group(['prefix' => '/v1/backup', 'middleware' => 'validate.key'], function () {
|
||||||
Route::put("/create", [SettingsAPIController::class, 'createBackup']);
|
Route::put("/create", [SettingsAPIController::class, 'createBackup']);
|
||||||
Route::get("/content-download", [SettingsAPIController::class, 'downloadBackup']);
|
Route::get("/content-download", [SettingsAPIController::class, 'downloadBackup']);
|
||||||
Route::get("/files-download", [SettingsAPIController::class, 'downloadBackup']);
|
Route::get("/files-download", [SettingsAPIController::class, 'downloadBackup']);
|
||||||
});
|
});
|
||||||
|
|
||||||
//other
|
//other
|
||||||
Route::group(['prefix' => '/v1', 'middleware' => 'validate.token'], function () {
|
Route::group(['prefix' => '/v1', 'middleware' => 'validate.key'], function () {
|
||||||
Route::post("/files", [FileUploadAPIController::class, 'upload']);
|
Route::post("/files", [FileUploadAPIController::class, 'upload']);
|
||||||
Route::post("/reset", [InitAPIController::class, 'setupReset']);
|
Route::post("/reset", [InitAPIController::class, 'setupReset']);
|
||||||
Route::post("/mailer", [MailAPIController::class, 'sendNotify']);
|
Route::post("/mailer", [MailAPIController::class, 'sendNotify']);
|
||||||
|
|
Loading…
Add table
Reference in a new issue