v1.0 Initial commit of project
This commit is contained in:
748
pub/api/classes/API.php
Normal file
748
pub/api/classes/API.php
Normal file
@@ -0,0 +1,748 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
class API
|
||||
{
|
||||
public $conn;
|
||||
|
||||
# The user uuid that requested the API
|
||||
protected $user_uuid;
|
||||
|
||||
# $user_type is either an API call (api) or an call from the frontend (frontend)
|
||||
protected $user_type;
|
||||
|
||||
# Either GET POST PUT or DELETE
|
||||
public $request_method;
|
||||
|
||||
protected $content_type;
|
||||
|
||||
# The original posted data to the API, this data is NOT sanitized and validated, never use this data for queries!
|
||||
public $postedData;
|
||||
|
||||
# The validated and sanitized data can be uses for the API actions
|
||||
public $data;
|
||||
|
||||
# The permission of the user to check if the action is allowed.
|
||||
public $permissions;
|
||||
|
||||
# The return url that the frontend request will forward to after the api call is done. if set to false it will only output
|
||||
# the json response with an http code. API calls always respond with json. $return_url can be set to supply the form with an input
|
||||
# with the name _return and value of the url to return to.
|
||||
public $return_url;
|
||||
|
||||
# Required fields & optional fields set by the API actions. This is an array like:
|
||||
# Example:
|
||||
# 'user_uuid' => ['type' => 'string', 'min' => 5, 'max' => 36],
|
||||
# 'user_enabled' => ['type' => 'int', 'min' => 0, 'max' => 99],
|
||||
# 'user_active' => ['type' => 'enum', 'values' => ['active', 'inactive', 'banned']],
|
||||
# 'user_email' => ['type' => 'string', 'format' => 'email'],
|
||||
private $requiredFields = [];
|
||||
private $optionalFields = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
# Setup Database connection
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/db_connect.php';
|
||||
$this->conn = $GLOBALS['conn'];
|
||||
|
||||
if (!empty($_SESSION['user']['user_uuid'])) {
|
||||
$this->InitUserTypeFrontend();
|
||||
} else {
|
||||
$this->InitUserTypeAPI();
|
||||
}
|
||||
|
||||
$this->return_url = $this->setReturnUrl();
|
||||
|
||||
# user_uuid will be set if the user is authorized
|
||||
if (!$this->user_uuid) {
|
||||
$this->apiOutput(401, ['error' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
# Only allow POST, GET, PUT and DELETE
|
||||
if (!$this->checkRequestMethod()) {
|
||||
$this->apiOutput(405, ['error' => 'Method not allowed']);
|
||||
}
|
||||
|
||||
|
||||
if (!$this->checkContentType()) {
|
||||
$this->apiOutput(400, ['error' => 'Unsupported Content-Type.']);
|
||||
}
|
||||
|
||||
if ($this->content_type === 'application/json') {
|
||||
if (!$this->checkJson()) {
|
||||
$this->apiOutput(400, ['error' => 'Invalid JSON format']);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable builder input for non-GET requests to prevent potential SQL injection vulnerabilities.
|
||||
// Also disable the builder for users with the 'frontend' user type as an extra security measure.
|
||||
// The builder should only be active for API users making GET requests.
|
||||
// When building a frontend page, you can still programmatically construct a builder array
|
||||
// and set it via $_GET like so after the API class creation:
|
||||
// $_GET['builder'] = [1 => ['where' => [0 => 'permission_uuid', 1 => $permission_uuid]]];
|
||||
if ($this->request_method !== 'GET' || $this->user_type === 'frontend') {
|
||||
$this->disableBuilder();
|
||||
}
|
||||
|
||||
# This converts the posted data if needed to an PHP array
|
||||
$this->postedData = $this->processPostedData();
|
||||
|
||||
}
|
||||
|
||||
private function InitUserTypeFrontend()
|
||||
{
|
||||
$this->user_uuid = $_SESSION['user']['user_uuid'];
|
||||
$this->user_type = 'frontend';
|
||||
|
||||
# Load the locale for the user, this is used for the return message in the frontend and other globalFunctions.
|
||||
include_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/Functions/globalFunctions.php';
|
||||
$locale = getPreferredLocale();
|
||||
global $translations;
|
||||
$translations = require $_SERVER['DOCUMENT_ROOT'] . "/bin/locales/{$locale}.php";
|
||||
}
|
||||
|
||||
protected function RecursiveDeleteFolder($folderPath): bool
|
||||
{
|
||||
// Check if the folder exists
|
||||
if (!is_dir($folderPath)) {
|
||||
$this->apiOutput(500, ['error' => 'directory not found: ' . $folderPath]);
|
||||
}
|
||||
|
||||
// Get all files and folders in the directory
|
||||
$items = array_diff(scandir($folderPath), array('.', '..'));
|
||||
|
||||
// Loop through each item
|
||||
foreach ($items as $item) {
|
||||
|
||||
$itemPath = $folderPath . DIRECTORY_SEPARATOR . $item;
|
||||
|
||||
if (is_dir($itemPath)) {
|
||||
if (!$this->RecursiveDeleteFolder($itemPath)) {
|
||||
$this->apiOutput(500, ['error' => "Unable to remove directory: $itemPath"]);
|
||||
}
|
||||
} else {
|
||||
if (!unlink($itemPath)) {
|
||||
$this->apiOutput(500, ['error' => "Unable to delete file: $itemPath"]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Remove the main folder after all contents are gone
|
||||
if (!rmdir($folderPath)) {
|
||||
$this->apiOutput(500, ['error' => "Unable to remove directory: $folderPath"]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function InitUserTypeAPI()
|
||||
{
|
||||
$this->user_type = 'api';
|
||||
|
||||
$headers = getallheaders();
|
||||
$authHeader = $headers['Authorization'] ?? '';
|
||||
|
||||
if (!preg_match('/^Bearer\s+(.+)$/', $authHeader, $matches)) {
|
||||
$this->apiOutput(401, ['error' => 'Unauthorized, missing bearer token.']);
|
||||
}
|
||||
|
||||
$bearerToken = trim($matches[1]);
|
||||
|
||||
if (!preg_match('/^[a-f0-9\-]{36}\.[a-f0-9]{64}$/i', $bearerToken)) {
|
||||
$this->apiOutput(401, ['error' => 'Unauthorized, invalid token format.']);
|
||||
}
|
||||
|
||||
[$tokenId, $tokenSecret] = explode('.', $bearerToken, 2);
|
||||
|
||||
$this->user_uuid = $this->validateToken($tokenId, $tokenSecret);
|
||||
|
||||
if ($this->user_uuid === false) {
|
||||
$this->apiOutput(401, ['error' => 'Unauthorized, invalid or expired token.']);
|
||||
}
|
||||
|
||||
$api_token_last_used_timestamp = time();
|
||||
$stmt = $this->conn->prepare("UPDATE vc_api_tokens SET api_token_last_used_timestamp = ? WHERE api_token_uuid = ?");
|
||||
$stmt->bind_param("is", $api_token_last_used_timestamp, $tokenId);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function validateSingleData($value, $rules)
|
||||
{
|
||||
if (!$this->validateField($value, $rules)) {
|
||||
$this->apiOutput(400, ['error' => "Invalid value: $value"]);
|
||||
}
|
||||
|
||||
return $this->sanitizeData($value, $rules['type']);
|
||||
}
|
||||
|
||||
public function validateData($requiredFields, $optionalFields = [])
|
||||
{
|
||||
$inputData = $this->postedData;
|
||||
|
||||
$this->requiredFields = $requiredFields;
|
||||
$this->optionalFields = $optionalFields;
|
||||
$sanitizedData = [];
|
||||
|
||||
foreach ($this->requiredFields as $field => $rules) {
|
||||
|
||||
if (!array_key_exists($field, $inputData)) {
|
||||
$this->apiOutput(400, ['error' => "Missing required field: $field"]);
|
||||
}
|
||||
|
||||
$value = $inputData[$field];
|
||||
|
||||
if (!$this->validateField($value, $rules)) {
|
||||
$this->apiOutput(400, ['error' => "Invalid value for $field"]);
|
||||
}
|
||||
|
||||
$sanitizedData[$field] = $this->sanitizeData($value, $rules['type']);
|
||||
}
|
||||
|
||||
|
||||
// Check optional fields
|
||||
foreach ($this->optionalFields as $field => $rules) {
|
||||
if (isset($inputData[$field])) {
|
||||
$value = $inputData[$field];
|
||||
|
||||
if (!$this->validateField($value, $rules)) {
|
||||
$this->apiOutput(422, ['error' => "Invalid value for optional field: $field"]);
|
||||
}
|
||||
|
||||
$sanitizedData[$field] = $this->sanitizeData($value, $rules['type']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['builder']) && is_array($_GET['builder'])) {
|
||||
foreach ($_GET['builder'] as $builder) {
|
||||
if (!isset($builder['where']) || count($builder['where']) !== 2) {
|
||||
continue; // skip invalid builders
|
||||
}
|
||||
|
||||
$field = $builder['where'][0];
|
||||
$value = $builder['where'][1];
|
||||
|
||||
// Check if the field is allowed (in required or optional)
|
||||
$rules = $requiredFields[$field] ?? $optionalFields[$field] ?? null;
|
||||
if (!$rules) {
|
||||
$this->apiOutput(403, ['error' => "Field not allowed in query: $field"]);
|
||||
}
|
||||
|
||||
// Validate and sanitize
|
||||
if (!$this->validateField($value, $rules)) {
|
||||
$this->apiOutput(422, ['error' => "Invalid value for builder field: $field"]);
|
||||
}
|
||||
|
||||
$sanitizedData[$field] = $this->sanitizeData($value, $rules['type']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $sanitizedData;
|
||||
}
|
||||
|
||||
private function isValidLength($value, $rules)
|
||||
{
|
||||
$length = strlen($value);
|
||||
if (isset($rules['min']) && $length < $rules['min']) return false;
|
||||
if (isset($rules['max']) && $length > $rules['max']) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private function isValidNumberRange($value, $rules)
|
||||
{
|
||||
if (isset($rules['min']) && $value < $rules['min']) return false;
|
||||
if (isset($rules['max']) && $value > $rules['max']) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private function validateField($value, $rules)
|
||||
{
|
||||
switch ($rules['type']) {
|
||||
case 'string':
|
||||
if (!is_string($value)) return false;
|
||||
return $this->isValidLength($value, $rules);
|
||||
case 'slugify':
|
||||
if (!is_string($value) || !preg_match('/^[a-z0-9]+(-[a-z0-9]+)*$/', $value)) return false;
|
||||
return $this->isValidLength($value, $rules);
|
||||
|
||||
case 'boolean':
|
||||
if (is_bool($value)) return true;
|
||||
|
||||
if (is_string($value)) {
|
||||
$value = strtolower($value);
|
||||
return $value === 'true' || $value === 'false' || $value === '1' || $value === '0';
|
||||
}
|
||||
|
||||
if (is_int($value)) {
|
||||
return $value === 1 || $value === 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case 'email':
|
||||
if (!is_string($value)) return false;
|
||||
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) return false;
|
||||
return $this->isValidLength($value, $rules);
|
||||
|
||||
case 'password':
|
||||
if (!is_string($value)) return false;
|
||||
return $this->isValidLength($value, $rules);
|
||||
|
||||
case 'html':
|
||||
if (!is_string($value)) return false;
|
||||
return $this->isValidLength($value, $rules);
|
||||
|
||||
case 'int':
|
||||
if (!is_int($value) && !ctype_digit($value)) return false;
|
||||
$value = (int)$value;
|
||||
return $this->isValidNumberRange($value, $rules);
|
||||
|
||||
case 'float':
|
||||
// Accept floats or numeric strings
|
||||
if (!is_float($value) && !is_numeric($value)) {
|
||||
return false;
|
||||
}
|
||||
$value = (float)$value;
|
||||
return $this->isValidNumberRange($value, $rules);
|
||||
|
||||
case 'timestamp':
|
||||
if (is_null($value)) return true;
|
||||
if (!is_int($value) && !ctype_digit($value)) return false;
|
||||
$value = (int)$value;
|
||||
if ($value < 0) return false;
|
||||
$min = $rules['min'] ?? 1;
|
||||
$max = $rules['max'] ?? 4102444800;
|
||||
return $value >= $min && $value <= $max;
|
||||
|
||||
case 'enum':
|
||||
if (!isset($rules['values']) || !in_array($value, $rules['values'], true)) return false;
|
||||
return true;
|
||||
|
||||
case 'uuid':
|
||||
if (!is_string($value)) return false;
|
||||
return preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $value);
|
||||
|
||||
case 'base64':
|
||||
if (!is_string($value)) return false;
|
||||
return base64_encode(base64_decode($value, true)) === $value;
|
||||
|
||||
case 'uuid':
|
||||
if (!is_string($value)) return false;
|
||||
return preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $value);
|
||||
|
||||
case 'json':
|
||||
if (!is_string($value)) return false;
|
||||
json_decode($value);
|
||||
return json_last_error() === JSON_ERROR_NONE;
|
||||
|
||||
case 'array':
|
||||
if (!is_array($value)) return false;
|
||||
return $value;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function sanitizeData($value, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'string':
|
||||
case 'enum':
|
||||
case 'uuid':
|
||||
// Remove HTML tags and encode special characters
|
||||
return htmlspecialchars(strip_tags($value), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
case 'email':
|
||||
// Remove illegal characters from email address
|
||||
return filter_var($value, FILTER_SANITIZE_EMAIL);
|
||||
|
||||
case 'password':
|
||||
// Passwords may contain special characters; just trim spaces
|
||||
return trim($value);
|
||||
|
||||
case 'html':
|
||||
// Allow safe HTML, you can customize allowed tags
|
||||
return strip_tags($value, '<b><i><u><strong><em><p><br>');
|
||||
|
||||
case 'int':
|
||||
// Remove anything that's not a number
|
||||
return filter_var($value, FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
case 'base64':
|
||||
// Only allow base64 valid characters
|
||||
return preg_replace('/[^a-zA-Z0-9\/\+=]/', '', $value);
|
||||
|
||||
case 'boolean':
|
||||
if (is_string($value)) {
|
||||
$value = strtolower(trim($value));
|
||||
return in_array($value, ['true', '1'], true) ? true : false;
|
||||
}
|
||||
|
||||
return (bool)$value;
|
||||
|
||||
default:
|
||||
// Return as-is if unknown type
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function checkPermissions($permission_name, $accessRightsRequired, $returnBoolean = false)
|
||||
{
|
||||
$accessLevels = [
|
||||
'NA' => 0, // No Access
|
||||
'RO' => 1, // Read Only
|
||||
'RW' => 2, // Read Write
|
||||
];
|
||||
$query = "SELECT
|
||||
vc_permissions.permission_name,
|
||||
vc_user_group_permissions_portal.permission_value
|
||||
FROM vc_user_group_permissions_portal
|
||||
INNER JOIN vc_permissions ON vc_user_group_permissions_portal.permission_uuid =vc_permissions.permission_uuid
|
||||
INNER JOIN vc_users ON vc_user_group_permissions_portal.user_group_uuid = vc_users.user_group_uuid
|
||||
WHERE user_uuid = ? AND permission_name = ?";
|
||||
|
||||
|
||||
$stmt = $this->conn->prepare($query);
|
||||
$stmt->bind_param("ss", $this->user_uuid, $permission_name);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result()->fetch_assoc();
|
||||
|
||||
if (!$result) {
|
||||
if ($returnBoolean) {
|
||||
return false;
|
||||
}
|
||||
$this->apiOutput(500, ['error' => 'Did not find permission required']);
|
||||
}
|
||||
|
||||
$userAccess = $result['permission_value'];
|
||||
|
||||
if (!isset($accessLevels[$userAccess]) || !isset($accessLevels[$accessRightsRequired])) {
|
||||
if ($returnBoolean) {
|
||||
return false;
|
||||
}
|
||||
$this->apiOutput(500, ['error' => 'Server error.']);
|
||||
}
|
||||
|
||||
// Compare user's access level with the required access level
|
||||
if ($accessLevels[$userAccess] < $accessLevels[$accessRightsRequired]) {
|
||||
if ($returnBoolean) {
|
||||
return false;
|
||||
}
|
||||
$this->apiOutput(403, ['error' => 'Permission denied. You do not have the required access level.']);
|
||||
}
|
||||
|
||||
if ($returnBoolean) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function setReturnUrl()
|
||||
{
|
||||
if ($this->user_type !== 'frontend') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method === 'POST' && isset($_POST['_return'])) {
|
||||
return $_POST['_return'];
|
||||
}
|
||||
|
||||
if ($method === 'PUT') {
|
||||
parse_str(file_get_contents("php://input"), $putData);
|
||||
if (isset($putData['_return'])) {
|
||||
return $putData['_return'];
|
||||
}
|
||||
}
|
||||
if ($method === 'GET') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $_SERVER['HTTP_REFERER'];
|
||||
}
|
||||
|
||||
protected function checkRequestMethod()
|
||||
{
|
||||
$allowedMethods = ['GET', 'POST', 'PUT', 'DELETE'];
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? '';
|
||||
|
||||
if (!in_array($method, $allowedMethods)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# Since browser doesnt allow DELETE or PUTs from the frontend forms (apart from some javascript/ajax fuckery)
|
||||
# we need to check the _method POST value.
|
||||
if ($this->user_type === 'frontend' && $method === 'POST' && isset($_POST['_method'])) {
|
||||
$overrideMethod = strtoupper($_POST['_method']);
|
||||
|
||||
if (in_array($overrideMethod, ['PUT', 'DELETE'])) {
|
||||
$this->request_method = $overrideMethod;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->request_method = $method;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkJson()
|
||||
{
|
||||
$rawInput = file_get_contents('php://input');
|
||||
if (empty($rawInput)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
json_decode($rawInput, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function processPostedData()
|
||||
{
|
||||
if ($this->user_type === 'api') {
|
||||
return json_decode(file_get_contents("php://input"), true);
|
||||
}
|
||||
|
||||
switch ($this->request_method) {
|
||||
case 'GET':
|
||||
return $_GET;
|
||||
case 'POST':
|
||||
return $_POST;
|
||||
case 'PUT':
|
||||
case 'DELETE':
|
||||
# When an image is uploaded from the front end the data needs to be specified its in $_POST and not $_FILES
|
||||
if ($this->content_type === 'multipart/form-data') {
|
||||
return $_POST;
|
||||
} else {
|
||||
parse_str(file_get_contents("php://input"), $data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
protected function validateToken(string $tokenId, string $tokenSecret)
|
||||
{
|
||||
$stmt = $this->conn->prepare("SELECT user_uuid, api_token FROM vc_api_tokens WHERE api_token_uuid = ? AND api_token_expiration_timestamp > UNIX_TIMESTAMP()");
|
||||
$stmt->bind_param("s", $tokenId);
|
||||
$stmt->execute();
|
||||
|
||||
$row = $stmt->get_result()->fetch_assoc();
|
||||
|
||||
if (!$row) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!password_verify($tokenSecret, $row['api_token'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $row['user_uuid'];
|
||||
}
|
||||
|
||||
|
||||
protected function checkContentType()
|
||||
{
|
||||
# api will need to post with an application/json type Content type.
|
||||
# frontend will post with application/x-www-form-urlencoded content type but also is capable of application/json
|
||||
# frontend can also post multipart/form-data
|
||||
# GET requests dont have an content type
|
||||
|
||||
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
||||
|
||||
if ($this->request_method === 'GET') {
|
||||
$this->content_type = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->user_type === 'api') {
|
||||
$this->content_type = 'application/json';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strpos($contentType, 'application/json') !== false) {
|
||||
$this->content_type = 'application/json';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strpos($contentType, 'application/x-www-form-urlencoded') !== false) {
|
||||
$this->content_type = 'application/x-www-form-urlencoded';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strpos($contentType, 'multipart/form-data') !== false) {
|
||||
$this->content_type = 'multipart/form-data';
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getUserUuid()
|
||||
{
|
||||
return $this->user_uuid;
|
||||
}
|
||||
|
||||
public function apiOutput($code = 200, $data = [], $frontendMessage = false)
|
||||
{
|
||||
if ($this->user_type === 'api') {
|
||||
http_response_code($code);
|
||||
header('Content-Type: application/json');
|
||||
if ($code === 200) {
|
||||
echo json_encode(reset($data));
|
||||
} else {
|
||||
echo json_encode($data);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if ($this->user_type === 'frontend') {
|
||||
if (in_array($this->request_method, ['POST', 'PUT', 'DELETE'])) {
|
||||
http_response_code($code);
|
||||
|
||||
if ($this->return_url) { # sometimes the PUT doesnt need an return or response set (Think of js actions to api from frontend)
|
||||
$_SESSION['response'] = json_encode($data);
|
||||
|
||||
# When a request is successfull the api will recieve the data, the frontend needs a friendly message
|
||||
if ($frontendMessage) {
|
||||
$_SESSION['response'] = json_encode([key($data) => __($frontendMessage)]);
|
||||
}
|
||||
|
||||
header('Location: ' . $this->return_url);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
public function prepareStatement($query)
|
||||
{
|
||||
// Enable MySQLi to throw exceptions on errors
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
|
||||
try {
|
||||
$stmt = $this->conn->prepare($query);
|
||||
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
// If an error occurs during prepare, catch it and return a proper response
|
||||
$this->apiOutput(500, ['error' => 'Database error: ' . $e->getMessage()]);
|
||||
return null;
|
||||
}
|
||||
|
||||
return $stmt;
|
||||
|
||||
}
|
||||
|
||||
public function executeStatement($stmt)
|
||||
{
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
return true;
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
if ($e->getCode() === 1451) {
|
||||
$this->apiOutput(409, ['error' => 'Cannot delete record: dependent data exists.']);
|
||||
} else {
|
||||
$this->apiOutput(500, ['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function isSuperuser()
|
||||
{
|
||||
$query = "SELECT * FROM vc_users WHERE vc_users.user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->user_uuid);
|
||||
$this->executeStatement($stmt);
|
||||
$result = $stmt->get_result();
|
||||
$user_data = $result->fetch_assoc();
|
||||
if ($user_data['user_email'] == 'superuser') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildDynamicQuery(string $tableName): array
|
||||
{
|
||||
$baseQuery = "SELECT * FROM " . $tableName;
|
||||
$whereClauses = [];
|
||||
$types = '';
|
||||
$values = [];
|
||||
|
||||
if (!isset($_GET['builder']) || !is_array($_GET['builder'])) {
|
||||
return [$baseQuery, $types, $values];
|
||||
}
|
||||
|
||||
foreach ($_GET['builder'] as $builder) {
|
||||
if (!isset($builder['where']) || !is_array($builder['where']) || count($builder['where']) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$column = $builder['where'][0];
|
||||
$value = $builder['where'][1];
|
||||
|
||||
$whereClauses[] = "$column = ?";
|
||||
$types .= 's';
|
||||
$values[] = $value;
|
||||
}
|
||||
|
||||
if (!empty($whereClauses)) {
|
||||
$baseQuery .= " WHERE " . implode(" AND ", $whereClauses);
|
||||
}
|
||||
|
||||
return [$baseQuery, $types, $values];
|
||||
}
|
||||
|
||||
protected function generalGetFunction($query, $types, $params, $returnBoolean, $itemName)
|
||||
{
|
||||
$stmt = $this->prepareStatement($query);
|
||||
|
||||
if (!empty($params)) {
|
||||
$stmt->bind_param($types, ...$params);
|
||||
}
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows === 0) {
|
||||
if (!$returnBoolean) {
|
||||
$this->apiOutput(404, ['error' => $itemName . ' not found.']);
|
||||
}
|
||||
}
|
||||
|
||||
$tokens = [];
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$tokens[] = $row;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function disableBuilder(): void
|
||||
{
|
||||
if (isset($_GET['builder'])) {
|
||||
unset($_GET['builder']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
108
pub/api/classes/API_apitoken.php
Normal file
108
pub/api/classes/API_apitoken.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_apitoken extends API
|
||||
{
|
||||
public function getTokens()
|
||||
{
|
||||
$query = "SELECT * FROM vc_api_tokens WHERE vc_api_tokens.user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['user_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$tokens = [];
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$tokens[] = $row;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function createNewToken()
|
||||
{
|
||||
|
||||
$api_token = bin2hex(random_bytes(64 / 2));
|
||||
|
||||
|
||||
$api_token_hash = password_hash($api_token, PASSWORD_BCRYPT, ["cost" => 12]);
|
||||
$api_token_expiration_timestamp = strtotime('+1 year');
|
||||
$query = "INSERT INTO vc_api_tokens (api_token_uuid, user_uuid, api_token, api_token_expiration_timestamp, api_token_created_timestamp) VALUES (UUID(), ?, ?, ?, ?)";
|
||||
|
||||
$stmt = $this->prepareStatement($query);
|
||||
|
||||
$stmt->bind_param('ssii', $this->data['user_uuid'], $api_token_hash, $api_token_expiration_timestamp, time());
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$result = $this->getNewToken();
|
||||
$_SESSION['tmp_api_token'] = $api_token;
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
$api_token_data = $result->fetch_assoc();
|
||||
|
||||
$_SESSION['tmp_api_token'] = $api_token_data['api_token_uuid'] . '.' . $api_token;
|
||||
|
||||
$this->apiOutput(200, ['success' => $api_token_data], 'api_token_created');
|
||||
} else {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the token on the server.'], 'error_contact_support');
|
||||
}
|
||||
}
|
||||
|
||||
public function getNewToken()
|
||||
{
|
||||
$query = "SELECT * FROM vc_api_tokens WHERE user_uuid = ? ORDER BY api_token_created_timestamp DESC LIMIT 1";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['user_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
return $stmt->get_result();
|
||||
}
|
||||
|
||||
|
||||
public function getToken()
|
||||
{
|
||||
$query = "SELECT vc_users.user_email, vc_users.user_uuid FROM vc_api_tokens INNER JOIN vc_users ON vc_api_tokens.user_uuid = vc_users.user_uuid WHERE api_token_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['api_token_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows === 0) {
|
||||
$this->apiOutput(404, ['error' => 'API token not found.']);
|
||||
}
|
||||
|
||||
$api_token_data = $result->fetch_assoc();
|
||||
|
||||
return $api_token_data;
|
||||
}
|
||||
|
||||
public function deleteToken()
|
||||
{
|
||||
$query = "DELETE FROM vc_api_tokens WHERE api_token_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['api_token_uuid']);
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'API token deleted successfully.']);
|
||||
}
|
||||
}
|
||||
|
||||
public function revokeToken()
|
||||
{
|
||||
|
||||
$api_token_revoked = ($this->data['api_token_revoked']) ? 1 : 0;
|
||||
|
||||
$query = "UPDATE vc_api_tokens SET api_token_revoked = ? WHERE api_token_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('is', $api_token_revoked, $this->data['api_token_uuid']);
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'API token ' . ($api_token_revoked ? 're' : 'en') . 'voked successfully.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
pub/api/classes/API_companies.php
Normal file
20
pub/api/classes/API_companies.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_companies extends API
|
||||
{
|
||||
public function updateCompanyState()
|
||||
{
|
||||
$query = "UPDATE companies SET company_state = ? WHERE company_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ss', $this->data['company_state'], $this->data['company_uuid']);
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'company state successfully updated']);
|
||||
}
|
||||
}
|
||||
}
|
||||
130
pub/api/classes/API_devices.php
Normal file
130
pub/api/classes/API_devices.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
use api\classes\imageProcessor;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_devices extends API
|
||||
{
|
||||
|
||||
public function getDevices($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('vc_devices');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'Device');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
private function getDeviceSlugify()
|
||||
{
|
||||
$query = "SELECT * FROM vc_devices WHERE device_slugify = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $this->data['device_slugify']);
|
||||
$this->executeStatement($stmt);
|
||||
return $stmt->get_result();
|
||||
}
|
||||
|
||||
public function createDeviceImage($imageRestrictions)
|
||||
{
|
||||
try {
|
||||
# Main image
|
||||
$imageProcessor = new imageProcessor('device_image');
|
||||
$imageProcessor->imageRestrictions = $imageRestrictions;
|
||||
$imageProcessor->validateAndProcess();
|
||||
$ImageData = $imageProcessor->returnBase64image();
|
||||
} catch (Exception $e) {
|
||||
$this->apiOutput(401, ['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
return $ImageData;
|
||||
}
|
||||
|
||||
public function createDevice()
|
||||
{
|
||||
|
||||
if (isset($this->data['device_image'])) {
|
||||
$query = "INSERT INTO vc_devices (device_uuid, device_vendor_uuid, device_type, device_name, device_slugify, device_enabled, device_notes, device_eol, device_extensions, device_extra, device_create_timestamp, device_image, device_image_thumbnail)
|
||||
VALUES (UUID(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssssisississ", $this->data['device_vendor_uuid'], $this->data['device_type'], $this->data['device_name'], $this->data['device_slugify'], $this->data['device_enabled'], $this->data['device_notes'], $this->data['device_eol'], $this->data['device_extensions'], $this->data['device_extra'], time(), $this->data['device_image'], $this->data['device_image_thumbnail']);
|
||||
} else {
|
||||
$query = "INSERT INTO vc_devices (device_uuid, device_vendor_uuid, device_type, device_name, device_slugify, device_enabled, device_notes, device_eol, device_extensions, device_extra, device_create_timestamp)
|
||||
VALUES (UUID(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssssisissi", $this->data['device_vendor_uuid'], $this->data['device_type'], $this->data['device_name'], $this->data['device_slugify'], $this->data['device_enabled'], $this->data['device_notes'], $this->data['device_eol'], $this->data['device_extensions'], $this->data['device_extra'], time());
|
||||
}
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$result = $this->getDeviceSlugify();
|
||||
if ($result->num_rows === 0) {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the device.'], 'error_contact_support');
|
||||
}
|
||||
|
||||
$createDirsFailed = false;
|
||||
$dirsToCreate = array(
|
||||
$_SERVER['DOCUMENT_ROOT'] . "/data/devices/" . $this->data['device_slugify'],
|
||||
$_SERVER['DOCUMENT_ROOT'] . "/data/devices/" . $this->data['device_slugify'] . "/firmware",
|
||||
$_SERVER['DOCUMENT_ROOT'] . "/data/devices/" . $this->data['device_slugify'] . "/documents"
|
||||
);
|
||||
|
||||
foreach ($dirsToCreate as $dir) {
|
||||
if (!file_exists($dir)) {
|
||||
if (!mkdir($dir)) {
|
||||
$createDirsFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($createDirsFailed) {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the device on the server.'], 'error_contact_support');
|
||||
}
|
||||
|
||||
$platform_data = $result->fetch_assoc();
|
||||
|
||||
$this->apiOutput(200, ['success' => $platform_data], 'item_added');
|
||||
}
|
||||
|
||||
public function updateDevice()
|
||||
{
|
||||
if (isset($this->data['device_image'])) {
|
||||
$query = "UPDATE vc_devices SET device_modified_timestamp = ?, device_vendor_uuid = ?, device_name = ?, device_enabled = ?, device_notes = ?, device_eol = ?, device_extensions = ?, device_extra = ?, device_image = ?, device_image_thumbnail = ? WHERE device_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("issisisssss", time(), $this->data['device_vendor_uuid'], $this->data['device_name'], $this->data['device_enabled'], $this->data['device_notes'], $this->data['device_eol'], $this->data['device_extensions'], $this->data['device_extra'], $this->data['device_image'], $this->data['device_image_thumbnail'], $this->data['device_uuid']);
|
||||
} else {
|
||||
$query = "UPDATE vc_devices SET device_modified_timestamp = ?, device_vendor_uuid = ?, device_name = ?, device_enabled = ?, device_notes = ?, device_eol = ?, device_extensions = ?, device_extra = ? WHERE device_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("issisisss", time(), $this->data['device_vendor_uuid'], $this->data['device_name'], $this->data['device_enabled'], $this->data['device_notes'], $this->data['device_eol'], $this->data['device_extensions'], $this->data['device_extra'], $this->data['device_uuid']);
|
||||
}
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Device updated successfully.']);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteDevice()
|
||||
{
|
||||
# check if the device exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'device_uuid', 1 => $this->data['device_uuid']]]];
|
||||
$device = $this->getDevices()[0];
|
||||
|
||||
# remove from database
|
||||
$query = "DELETE FROM vc_devices WHERE device_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $device['device_uuid']);
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
# Delete the device data folder.
|
||||
$dirsToDelete = $_SERVER['DOCUMENT_ROOT'] . "/data/devices/" . $device['device_slugify'];
|
||||
$this->RecursiveDeleteFolder($dirsToDelete);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'Device removed successfully.']);
|
||||
}
|
||||
}
|
||||
478
pub/api/classes/API_inserve.php
Normal file
478
pub/api/classes/API_inserve.php
Normal file
@@ -0,0 +1,478 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_inserve extends API
|
||||
{
|
||||
|
||||
private $inserve_url;
|
||||
|
||||
private $inserve_token;
|
||||
|
||||
public $inserve_source_uuid;
|
||||
|
||||
private $ch;
|
||||
public $httpCode = false;
|
||||
|
||||
public $response = false;
|
||||
|
||||
private $cloudDistrubutor = 'digistate-servers';
|
||||
|
||||
public function setupConnection()
|
||||
{
|
||||
$query = "SELECT * FROM system_sources WHERE source_name = 'inserve'";
|
||||
$result = $this->conn->query($query)->fetch_assoc();
|
||||
|
||||
$this->inserve_url = $result['source_url'];
|
||||
$this->inserve_token = $result['source_auth_token'];
|
||||
$this->inserve_source_uuid = $result['source_uuid'];
|
||||
}
|
||||
|
||||
public function execCurl()
|
||||
{
|
||||
$this->response = curl_exec($this->ch);
|
||||
$this->httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($this->ch);
|
||||
}
|
||||
|
||||
public function returnResponse()
|
||||
{
|
||||
$this->apiOutput($this->httpCode, json_decode($this->response, true));
|
||||
}
|
||||
|
||||
public function authMe()
|
||||
{
|
||||
$this->ch = curl_init($this->inserve_url . 'auth/me');
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json"
|
||||
]
|
||||
]);
|
||||
$this->execCurl();
|
||||
}
|
||||
|
||||
public function getLinkedCompanies()
|
||||
{
|
||||
$this->ch = curl_init($this->inserve_url . 'cloud-distributors/digistate-servers/companies');
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json"
|
||||
]
|
||||
]);
|
||||
$this->execCurl();
|
||||
}
|
||||
|
||||
public function companies($page)
|
||||
{
|
||||
// Build array the way the API expects
|
||||
$params = [
|
||||
'b' => [
|
||||
['orderBy' => ['name', 'ASC']],
|
||||
['orderBy' => ['id', 'DESC']],
|
||||
['with' => ['operator', 'country']],
|
||||
['paginate' => 300],
|
||||
],
|
||||
'page' => $page
|
||||
];
|
||||
|
||||
$query = http_build_query($params);
|
||||
|
||||
$this->ch = curl_init($this->inserve_url . 'companies?' . $query);
|
||||
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json"
|
||||
]
|
||||
]);
|
||||
|
||||
$this->execCurl();
|
||||
|
||||
return json_decode($this->response, true);
|
||||
}
|
||||
|
||||
|
||||
public function syncCompaniesFromSentri()
|
||||
{
|
||||
# First retrieve all the active companies to sync to the Inserver cloud distributor
|
||||
$companies = [];
|
||||
|
||||
$sql = "SELECT company_source_id FROM companies WHERE company_state = 'active'";
|
||||
$stmt = $this->conn->query($sql);
|
||||
while ($row = $stmt->fetch_assoc()) {
|
||||
$id = (int)$row['company_source_id'];
|
||||
$companies[] = [
|
||||
'cloud_distribution_id' => (string)$id,
|
||||
'company_id' => $id
|
||||
];
|
||||
}
|
||||
|
||||
$url = $this->inserve_url . 'cloud-distributors/digistate-servers/companies';
|
||||
|
||||
$this->ch = curl_init($url);
|
||||
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($companies),
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json",
|
||||
"Content-Type: application/json"
|
||||
],
|
||||
]);
|
||||
|
||||
$this->execCurl();
|
||||
}
|
||||
|
||||
public function getCloudSubscriptions()
|
||||
{
|
||||
|
||||
$this->ch = curl_init($this->inserve_url . 'cloud-distribution-subscriptions/');
|
||||
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json"
|
||||
]
|
||||
]);
|
||||
|
||||
$this->execCurl();
|
||||
}
|
||||
|
||||
public function updateSubscription($subscriptionId = false, $payload = false)
|
||||
{
|
||||
$url = $this->inserve_url . 'cloud-distribution-subscriptions/' . $subscriptionId;
|
||||
|
||||
$this->ch = curl_init($url);
|
||||
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CUSTOMREQUEST => 'PUT',
|
||||
CURLOPT_POSTFIELDS => json_encode($payload),
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json",
|
||||
"Content-Type: application/json"
|
||||
],
|
||||
]);
|
||||
|
||||
$this->execCurl();
|
||||
}
|
||||
|
||||
private function getAllTypes($type)
|
||||
{
|
||||
$allowedColumns = [
|
||||
'server_licenses',
|
||||
'server_backup'
|
||||
];
|
||||
|
||||
if (!in_array($type, $allowedColumns, true)) {
|
||||
throw new Exception('Invalid column name');
|
||||
}
|
||||
|
||||
$query = "SELECT `$type` FROM servers";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$this->executeStatement($stmt);
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$servers = [];
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
array_push($servers, $row);
|
||||
}
|
||||
|
||||
$allTypes = [];
|
||||
foreach ($servers as $server) {
|
||||
if (!empty($server[$type])) {
|
||||
$types = json_decode($server[$type], true);
|
||||
if (is_array($types)) {
|
||||
foreach ($types as $item) {
|
||||
foreach ($item as $key => $value) {
|
||||
$allTypes[$key . '.' . $value] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $allTypes;
|
||||
}
|
||||
|
||||
private function calculateTotalDiskUsage($diskJson)
|
||||
{
|
||||
$disks = json_decode($diskJson, true);
|
||||
$server_disks_count = 0;
|
||||
if (is_array($disks)) {
|
||||
foreach ($disks as $disk) {
|
||||
$server_disks_count += $disk['disk_space'];
|
||||
}
|
||||
}
|
||||
if (is_array($disks) && count($disks) > 0) {
|
||||
$sizes = array_column($disks, 'disk_space');
|
||||
$server_disks_count = array_sum($sizes);
|
||||
}
|
||||
return $server_disks_count;
|
||||
}
|
||||
|
||||
private function buildCountObject(string $serverUuid, string $key): array
|
||||
{
|
||||
return [
|
||||
'countSentri' => 0,
|
||||
'countInserve' => 0,
|
||||
'sentriCompanyId' => 0,
|
||||
'SentriStatus' => 0,
|
||||
'subscriptionInserveExists' => false,
|
||||
'subscriptionInserveId' => false,
|
||||
'subscriptionInserveCompanyId' => false,
|
||||
'subscriptionInserveName' => false,
|
||||
'subscriptionInserveStatus' => 0,
|
||||
'md5' => md5($serverUuid . ':' . $key),
|
||||
];
|
||||
}
|
||||
|
||||
private function transformTypes(array $types, string $serverUuid): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($types as $key => $value) {
|
||||
$result[$key] = $this->buildCountObject($serverUuid, $key);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function buildCountArray($serverUuid)
|
||||
{
|
||||
$allBackupTypes = $this->getAllTypes('server_backup');
|
||||
$allLicenseTypes = $this->getAllTypes('server_licenses');
|
||||
|
||||
$backupCounts = $this->transformTypes($allBackupTypes, $serverUuid);
|
||||
$licenseCounts = $this->transformTypes($allLicenseTypes, $serverUuid);
|
||||
|
||||
return array_merge(
|
||||
[
|
||||
"server_CPU_count" => $this->buildCountObject($serverUuid, 'server_cpu_count'),
|
||||
"server_Memory_count" => $this->buildCountObject($serverUuid, 'server_memory_count'),
|
||||
"server_Disk_space_count" => $this->buildCountObject($serverUuid, 'server_disks_count'),
|
||||
],
|
||||
$licenseCounts,
|
||||
$backupCounts
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function syncServerLicencesToInserve()
|
||||
{
|
||||
# Get all the linked companies
|
||||
$this->getLinkedCompanies();
|
||||
$allCompanies = json_decode($this->response, true);
|
||||
$allCompaniesIds = array_column($allCompanies['matched'], 'id', 'company_id');
|
||||
|
||||
# first get the current subscriptions
|
||||
$this->getCloudSubscriptions();
|
||||
$allInserveSubscriptions = json_decode($this->response, true);
|
||||
|
||||
# Filter out all the none Sentri posted subscriptions based on the name for performance
|
||||
$allInserveSubscriptions = array_filter($allInserveSubscriptions, function ($subscription) {
|
||||
return isset($subscription['cloud_subscription_id']) && $subscription['cloud_subscription_id'] === 'sentri-servers';
|
||||
});
|
||||
|
||||
# Build lookup of existing Inserve subscriptions by cloud_distribution_id
|
||||
# this will be used later to lookup
|
||||
$inserveLookup = [];
|
||||
foreach ($allInserveSubscriptions as $subscription) {
|
||||
if (!empty($subscription['cloud_distribution_id'])) {
|
||||
$inserveLookup[$subscription['cloud_distribution_id']] = [
|
||||
'id' => (int)$subscription['id'],
|
||||
'quantity' => (int)$subscription['quantity'],
|
||||
'status' => (int)$subscription['status'],
|
||||
'cloud_distribution_company_id' => (int)$subscription['cloud_distribution_company_id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
# get all the servers from Sentri
|
||||
$sql = "SELECT * FROM servers INNER JOIN companies ON servers.company_uuid = companies.company_uuid WHERE company_state = 'active' AND server_state != 'new' AND server_state != 'disabled' ";
|
||||
$stmt = $this->conn->query($sql);
|
||||
|
||||
while ($row = $stmt->fetch_assoc()) {
|
||||
# Create a count of all the Subscriptions possible with every count on 0
|
||||
$subscriptionCounts = $this->buildCountArray($row['server_uuid']);
|
||||
$totalDiskSpace = $this->calculateTotalDiskUsage($row['server_disks']);
|
||||
|
||||
# Inserve status codes are:
|
||||
# 0 = active, 1 = cancelled, 2 = pending, 3 = trial, 4 = on hold, 5 = removed
|
||||
$statusMap = [
|
||||
'active' => 0,
|
||||
'trial' => 3,
|
||||
'deleted' => 5,
|
||||
];
|
||||
|
||||
// if no states matched there is something terrifying wrong, call the ambulance!
|
||||
if (!isset($statusMap[$row['server_state']])) {
|
||||
exit;
|
||||
}
|
||||
$sentriStatus = $statusMap[$row['server_state']];
|
||||
|
||||
# Set all the server resource counts from Sentri into the $subscriptionCounts
|
||||
$subscriptionCounts['server_CPU_count']['countSentri'] = $row['server_cpu'];
|
||||
$subscriptionCounts['server_Memory_count']['countSentri'] = (int)ceil($row['server_memory'] / 1024);
|
||||
$subscriptionCounts['server_Disk_space_count']['countSentri'] = $totalDiskSpace;
|
||||
|
||||
$licenses = json_decode($row['server_licenses'], true);
|
||||
foreach ($licenses as $license) {
|
||||
foreach ($license as $key => $LicenseType) {
|
||||
$subscriptionCounts[$key . '.' . $LicenseType]['countSentri']++;
|
||||
}
|
||||
}
|
||||
|
||||
$backups = json_decode($row['server_backup'], true);
|
||||
foreach ($backups as $backup) {
|
||||
foreach ($backup as $key => $BackupType) {
|
||||
$subscriptionCounts[$key . '.' . $BackupType]['countSentri'] = $totalDiskSpace;
|
||||
}
|
||||
}
|
||||
|
||||
# Mark subscriptions that already exist in Inserve
|
||||
foreach ($subscriptionCounts as $key => &$item) {
|
||||
if (!is_array($item) || !isset($item['md5'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$md5 = (string)$item['md5'];
|
||||
|
||||
if (isset($inserveLookup[$md5])) { # Subscription already exists in Inserve
|
||||
$item['SentriStatus'] = $sentriStatus;
|
||||
$item['sentriCompanyId'] = (int)$allCompaniesIds[$row['company_source_id']] ?? 0;
|
||||
$item['subscriptionInserveExists'] = true;
|
||||
$item['subscriptionInserveId'] = $inserveLookup[$item['md5']]['id'];
|
||||
$item['countInserve'] = $inserveLookup[$item['md5']]['quantity'];
|
||||
$item['subscriptionInserveCompanyId'] = $inserveLookup[$item['md5']]['cloud_distribution_company_id'];
|
||||
$item['subscriptionInserveStatus'] = $inserveLookup[$item['md5']]['status'];
|
||||
} else { # Subscription does not exists in Inserve
|
||||
$item['sentriCompanyId'] = (int)$allCompaniesIds[$row['company_source_id']] ?? 0;
|
||||
$item['subscriptionInserveExists'] = false;
|
||||
$item['subscriptionInserveId'] = false;
|
||||
$item['countInserve'] = 0;
|
||||
$item['subscriptionInserveCompanyId'] = false;
|
||||
}
|
||||
}
|
||||
unset($item);
|
||||
|
||||
// Make the subscriptions names look nice and dandy.
|
||||
foreach ($subscriptionCounts as $key => &$item) {
|
||||
// Set server name
|
||||
$serverName = $row['server_hostname'] ?? $row['server_vm_host_name'] ?? 'Unknown';
|
||||
|
||||
// remove server_ prefix and _count suffix
|
||||
$namePart = $key;
|
||||
if (str_starts_with($key, 'server_') && str_ends_with($key, '_count')) {
|
||||
$namePart = substr($key, 7, -6);
|
||||
$namePart = ucfirst($namePart);
|
||||
} // Handle keys with "."
|
||||
elseif (strpos($key, '.') !== false) {
|
||||
[$first, $second] = explode('.', $key, 2);
|
||||
if ($first === $second || strtolower($second) === 'yes') {
|
||||
$namePart = ucfirst($first);
|
||||
} else {
|
||||
$namePart = ucfirst($first) . ' - ' . $second;
|
||||
}
|
||||
} //Handle keys without . but with a space (expmale directadmin.Standard Discounted)
|
||||
elseif (strpos($key, ' ') !== false) {
|
||||
// explode on first .
|
||||
$parts = explode('.', $key, 2);
|
||||
if (count($parts) === 2) {
|
||||
$namePart = ucfirst($parts[0]) . ' - ' . $parts[1];
|
||||
} else {
|
||||
// Cap first word before first space
|
||||
$spacePos = strpos($key, ' ');
|
||||
$first = ucfirst(substr($key, 0, $spacePos));
|
||||
$rest = substr($key, $spacePos + 1);
|
||||
$namePart = $first . ' - ' . $rest;
|
||||
}
|
||||
}
|
||||
|
||||
$item['subscriptionInserveName'] = $serverName . ' - ' . $namePart;
|
||||
}
|
||||
unset($item);
|
||||
|
||||
foreach ($subscriptionCounts as $key => $item) {
|
||||
// if subscriptionInserveExists but the countInserve is null skip creation
|
||||
if ($item['subscriptionInserveExists'] === false && (int)$item['countSentri'] === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if subscriptionInserveExists is false create a new subscription
|
||||
if ($item['subscriptionInserveExists'] === false) {
|
||||
$payload = [
|
||||
"cloud_distribution_id" => $item['md5'], #md5 hash based on the server_uuid from sentri and the subscription name (eg. server_cpu_count)
|
||||
"cloud_subscription_id" => "sentri-servers", # Mark all the sentri-servers subscriptions so we can filter the subscriptions better
|
||||
"name" => $item['subscriptionInserveName'],
|
||||
"quantity" => $item['countSentri'],
|
||||
"cloud_distribution_company_id" => $item['sentriCompanyId'], # this is generated by inserve (306 = digistate)
|
||||
"status" => $item['SentriStatus'],
|
||||
"period_type" => 0, # 0 = monthly, 1 = anual, 2 = one time cost
|
||||
"start_date" => date('Y-m-d')
|
||||
];
|
||||
|
||||
$this->createSubscription($payload);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// update the subscription if the countInserve and countSentri dont match
|
||||
// Or when sentriCompanyId and subscriptionInserveCompanyId dont match
|
||||
if ((
|
||||
(int)$item['countInserve'] !== (int)$item['countSentri'] ||
|
||||
(int)$item['sentriCompanyId'] !== (int)$item['subscriptionInserveCompanyId'] ||
|
||||
(int)$item['SentriStatus'] !== (int)$item['subscriptionInserveStatus']
|
||||
)
|
||||
&& $item['subscriptionInserveExists'] !== false
|
||||
) {
|
||||
|
||||
|
||||
$payload = [
|
||||
"quantity" => (int)$item['countSentri'],
|
||||
"cloud_distribution_company_id" => (int)$item['sentriCompanyId'],
|
||||
"name" => $item['subscriptionInserveName'],
|
||||
"status" => $item['SentriStatus'],
|
||||
"quantity" => $item['countSentri']
|
||||
];
|
||||
$this->updateSubscription($item['subscriptionInserveId'], $payload);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function createSubscription($payload)
|
||||
{
|
||||
$url = $this->inserve_url . 'cloud-distribution-subscriptions';
|
||||
$this->ch = curl_init($url);
|
||||
|
||||
# I need to make this pay load:
|
||||
curl_setopt_array($this->ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($payload),
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"X-Api-Key: $this->inserve_token",
|
||||
"Accept: application/json",
|
||||
"Content-Type: application/json"
|
||||
],
|
||||
]);
|
||||
|
||||
$this->execCurl();
|
||||
}
|
||||
}
|
||||
30
pub/api/classes/API_mailsettings.php
Normal file
30
pub/api/classes/API_mailsettings.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_mailsettings extends API
|
||||
{
|
||||
public function updateMailSettings($updatePassword)
|
||||
{
|
||||
if ($updatePassword) {
|
||||
$query = "UPDATE vc_portal_settings SET mail_from_name = ?, mail_from_address = ?, mail_smtp_host = ?, mail_smtp_secure = ?, mail_smtp_port = ?, mail_smtp_auth = ?, mail_smtp_user = ?, mail_smtp_pass = ? WHERE portal_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssssiisss', $this->data['mail_from_name'], $this->data['mail_from_address'], $this->data['mail_smtp_host'], $this->data['mail_smtp_secure'], $this->data['mail_smtp_port'], $this->data['mail_smtp_auth'], $this->data['mail_smtp_user'], $this->data['mail_smtp_pass'], $this->data['portal_uuid']);
|
||||
|
||||
} else {
|
||||
$query = "UPDATE vc_portal_settings SET mail_from_name = ?, mail_from_address = ?, mail_smtp_host = ?, mail_smtp_secure = ?, mail_smtp_port = ?, mail_smtp_auth = ?, mail_smtp_user = ? WHERE portal_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssssiiss', $this->data['mail_from_name'], $this->data['mail_from_address'], $this->data['mail_smtp_host'], $this->data['mail_smtp_secure'], $this->data['mail_smtp_port'], $this->data['mail_smtp_auth'], $this->data['mail_smtp_user'], $this->data['portal_uuid']);
|
||||
|
||||
}
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'mail settings updated successfully.']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
40
pub/api/classes/API_mfa.php
Normal file
40
pub/api/classes/API_mfa.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_mfa extends API
|
||||
{
|
||||
public function disableMFA()
|
||||
{
|
||||
# Users cannot, by default disable MFA of other users
|
||||
if ($this->getUserUuid() != $this->data['user_uuid']) {
|
||||
$this->checkPermissions('admin-access-admins-mfa', 'RW');
|
||||
}
|
||||
|
||||
$query = "UPDATE vc_users SET user_two_factor_enabled = 0, user_two_factor_secret = NULL WHERE user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $this->data['user_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'mfa is disabled']);
|
||||
}
|
||||
|
||||
public function enableMFA()
|
||||
{
|
||||
# Users cannot, create MFA of other users
|
||||
if ($this->getUserUuid() != $this->data['user_uuid']) {
|
||||
$this->apiOutput(401, ['error' => 'you are not allowed to enable mfa for others']);
|
||||
}
|
||||
|
||||
$query = "UPDATE vc_users SET user_two_factor_enabled = 1, user_two_factor_secret = ? WHERE user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ss", $this->data['user_two_factor_secret'], $this->data['user_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'mfa is enabled']);
|
||||
}
|
||||
}
|
||||
32
pub/api/classes/API_office_stompjes.php
Normal file
32
pub/api/classes/API_office_stompjes.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_office_stompjes extends API
|
||||
{
|
||||
public function addStomp()
|
||||
{
|
||||
$query = "INSERT INTO office_stompjes (stomp_uuid, user_uuid, stomp_timestamp) VALUES (UUID(), ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('si', $this->data['user_uuid'], time());
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$this->apiOutput(200, ['success' => 'Stomp added.']);
|
||||
}
|
||||
|
||||
public function deleteStomp()
|
||||
{
|
||||
$query = "DELETE FROM office_stompjes WHERE stomp_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['stomp_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$this->apiOutput(200, ['success' => 'Stomp removed.']);
|
||||
}
|
||||
}
|
||||
123
pub/api/classes/API_permissions.php
Normal file
123
pub/api/classes/API_permissions.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_permissions extends API
|
||||
{
|
||||
public function getPermission($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('vc_permissions');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'Permission');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function deletePermission()
|
||||
{
|
||||
$query = "DELETE FROM vc_permissions WHERE permission_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['permission_uuid']);
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Permission deleted successfully.']);
|
||||
}
|
||||
}
|
||||
|
||||
public function createPermission()
|
||||
{
|
||||
# Check if permission slugify already exists
|
||||
$result = $this->getPermissionSlugify();
|
||||
if ($result->num_rows > 0) {
|
||||
$this->apiOutput(409, ['error' => 'Permission slugify already exists'], 'item_already_exists!');
|
||||
}
|
||||
|
||||
$query = "INSERT INTO vc_permissions (permission_uuid, permission_name, permission_slugify, permission_description, permission_create_timestamp, module_uuid) VALUES (UUID(), ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('sssis', $this->data['permission_name'], $this->data['permission_slugify'], $this->data['permission_description'], time(), $this->data['module_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$result = $this->getPermissionSlugify();
|
||||
if ($result->num_rows === 0) {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the platform on the server.'], 'error_contact_support');
|
||||
}
|
||||
|
||||
$permission_data = $result->fetch_assoc();
|
||||
|
||||
# Get all the groups so we can create the permissions for the group
|
||||
$user_groups = array();
|
||||
$sql = "SELECT * FROM vc_user_groups";
|
||||
$stmt = $this->conn->query($sql);
|
||||
while ($user_group = $stmt->fetch_assoc()) {
|
||||
array_push($user_groups, $user_group);
|
||||
}
|
||||
|
||||
# Update all the groups with the newly added permission
|
||||
foreach ($user_groups as $user_group) {
|
||||
$query = "INSERT INTO vc_user_group_permissions_portal (permission_uuid, user_group_uuid, permission_value) VALUES (?, ?, ?)";
|
||||
$permission_value = 'NA';
|
||||
if ($user_group['user_group_name'] == 'superuser') {
|
||||
$permission_value = 'RW';
|
||||
}
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("sss", $permission_data['permission_uuid'], $user_group['user_group_uuid'], $permission_value);
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
$this->apiOutput(200, ['success' => $permission_data], 'item_added');
|
||||
}
|
||||
|
||||
public function getPermissionSlugify()
|
||||
{
|
||||
$query = "SELECT * FROM vc_permissions WHERE permission_slugify = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $this->data['permission_slugify']);
|
||||
$this->executeStatement($stmt);
|
||||
return $stmt->get_result();
|
||||
}
|
||||
|
||||
public function updatePermission()
|
||||
{
|
||||
$query = "UPDATE vc_permissions SET permission_name = ?, permission_description = ?, permission_modified_timestamp = ?, module_uuid = ? WHERE permission_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssiss', $this->data['permission_name'], $this->data['permission_description'], time(), $this->data['module_uuid'], $this->data['permission_uuid']);
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Permission updated successfully.']);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateAccessRights()
|
||||
{
|
||||
$query = "UPDATE vc_user_group_permissions_portal SET permission_value = ? WHERE permission_uuid = ? AND user_group_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('sss', $this->data['permission_value'], $this->data['permission_uuid'], $this->data['user_group_uuid']);
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Access rights changed successfully.']);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPermissionRights()
|
||||
{
|
||||
$query = "SELECT * FROM vc_permissions
|
||||
INNER JOIN vc_user_group_permissions_portal ON vc_permissions.permission_uuid = vc_user_group_permissions_portal.permission_uuid
|
||||
INNER JOIN vc_user_groups ON vc_user_group_permissions_portal.user_group_uuid = vc_user_groups.user_group_uuid
|
||||
WHERE vc_permissions.permission_uuid = ? ORDER BY vc_user_groups.user_group_weight ASC";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['permission_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$access_rights = [];
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$access_rights[] = $row;
|
||||
}
|
||||
|
||||
return $access_rights;
|
||||
}
|
||||
}
|
||||
72
pub/api/classes/API_platforms.php
Normal file
72
pub/api/classes/API_platforms.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_platforms extends API
|
||||
{
|
||||
public function getPlatforms($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('vc_platforms');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'Platform');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
||||
public function createPlatforms()
|
||||
{
|
||||
if (isset($this->data['platform_image'])) {
|
||||
$query = "INSERT INTO vc_platforms (platform_uuid, platform_name, platform_slugify, platform_description, platform_enabled, platform_image, platform_create_timestamp) VALUES (UUID(), ?, ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('sssssi', $this->data['platform_name'], $this->data['platform_slugify'], $this->data['platform_description'], $this->data['platform_enabled'], $this->data['platform_image'], time());
|
||||
} else {
|
||||
$query = "INSERT INTO vc_platforms (platform_uuid, platform_name, platform_slugify, platform_description, platform_enabled, platform_create_timestamp) VALUES (UUID(), ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssssi', $this->data['platform_name'], $this->data['platform_slugify'], $this->data['platform_description'], $this->data['platform_enabled'], time());
|
||||
}
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$result = $this->getPlatformSlugify();
|
||||
if ($result->num_rows === 0) {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the platform on the server.'], 'error_contact_support');
|
||||
}
|
||||
|
||||
$platform_data = $result->fetch_assoc();
|
||||
|
||||
$this->apiOutput(200, ['success' => $platform_data], 'item_added');
|
||||
}
|
||||
|
||||
public function getPlatformSlugify()
|
||||
{
|
||||
$query = "SELECT * FROM vc_platforms WHERE platform_slugify = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $this->data['platform_slugify']);
|
||||
$this->executeStatement($stmt);
|
||||
return $stmt->get_result();
|
||||
}
|
||||
|
||||
public function editPlatforms()
|
||||
{
|
||||
if (isset($this->data['platform_image'])) {
|
||||
$query = "UPDATE vc_platforms SET platform_name = ?, platform_description = ?, platform_enabled = ?, platform_image = ?, platform_modified_timestamp = ? WHERE platform_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssisis", $this->data['platform_name'], $this->data['platform_description'], $this->data['platform_enabled'], $this->data['platform_image'], time(), $this->data['platform_uuid']);
|
||||
} else {
|
||||
$query = "UPDATE vc_platforms SET platform_name = ?, platform_description = ?, platform_enabled = ?, platform_modified_timestamp = ? WHERE platform_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssiis", $this->data['platform_name'], $this->data['platform_description'], $this->data['platform_enabled'], time(), $this->data['platform_uuid']);
|
||||
}
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Platform updated successfully.']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
21
pub/api/classes/API_portalsettings.php
Normal file
21
pub/api/classes/API_portalsettings.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_portalsettings extends API
|
||||
{
|
||||
public function updatePortalSettings()
|
||||
{
|
||||
$query = "UPDATE vc_portal_settings SET portal_name = ?, portal_provider_name = ?, admin_auth_methods = ? WHERE portal_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssss", $this->data['portal_name'], $this->data['portal_provider_name'], $this->data['admin_auth_methods'], $this->data['portal_uuid']);
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'portal settings updated successfully.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
pub/api/classes/API_resetpassword.php
Normal file
26
pub/api/classes/API_resetpassword.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_resetpassword extends API
|
||||
{
|
||||
public function resetPassword()
|
||||
{
|
||||
|
||||
$query = "UPDATE vc_users SET user_password = ?, user_password_reset_token = ?, user_password_reset_expires = ? WHERE user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssis",
|
||||
$this->data['user_password'],
|
||||
$this->data['user_password_reset_token'],
|
||||
$this->data['user_password_reset_expires'],
|
||||
$this->data['user_uuid']
|
||||
);
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
}
|
||||
}
|
||||
269
pub/api/classes/API_servers.php
Normal file
269
pub/api/classes/API_servers.php
Normal file
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
use JsonException;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_servers extends API
|
||||
{
|
||||
public function validateDiskData($disks)
|
||||
{
|
||||
foreach ($disks as $index => $disk) {
|
||||
|
||||
// Ensure $disk is an array
|
||||
if (!is_array($disk)) {
|
||||
$this->apiOutput(400, ['error' => "Disk entry is not an array"]);
|
||||
}
|
||||
|
||||
$requiredFields = ['disk_name', 'disk_space', 'disk_used', 'disk_location'];
|
||||
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!array_key_exists($field, $disk)) {
|
||||
$this->apiOutput(400, ['error' => "Missing required field '$field' in disk information"]);
|
||||
}
|
||||
switch ($field) {
|
||||
case 'disk_used':
|
||||
case 'disk_space':
|
||||
$disks[$index][$field] = $this->validateSingleData($disk[$field], ['type' => 'float']);
|
||||
break;
|
||||
case 'disk_location':
|
||||
case 'disk_name':
|
||||
$disks[$index][$field] = $this->validateSingleData($disk[$field], ['type' => 'string']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return json_encode($disks, JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $e) {
|
||||
$this->apiOutput(400, ['error' => "Failed to encode disk data to JSON: " . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function updateServer()
|
||||
{
|
||||
|
||||
if (isset($this->data['company_uuid'])) {
|
||||
if (strlen($this->data['company_uuid']) == 0) {
|
||||
$this->data['company_uuid'] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'company_uuid',
|
||||
'server_vm_id',
|
||||
'server_vm_host_id',
|
||||
'server_vm_host_name',
|
||||
'server_power_state',
|
||||
'server_state',
|
||||
'server_hostname',
|
||||
'server_os',
|
||||
'server_cpu',
|
||||
'server_memory',
|
||||
'server_memory_demand',
|
||||
'server_disks',
|
||||
'server_ipv4',
|
||||
'server_ipv6',
|
||||
'server_vm_generation',
|
||||
'server_vm_snapshot',
|
||||
'server_licenses',
|
||||
'server_backup',
|
||||
'server_description'
|
||||
];
|
||||
|
||||
$insertFields = ['server_uuid'];
|
||||
$insertValues = ['UUID()'];
|
||||
$bindParams = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if (array_key_exists($field, $this->data)) {
|
||||
$insertFields[] = $field;
|
||||
$insertValues[] = ":$field";
|
||||
$bindParams[":$field"] = $this->data[$field]; // can be NULL
|
||||
}
|
||||
}
|
||||
|
||||
# Always include server_create_timestamp and server_modified_timestamp
|
||||
$insertFields[] = 'server_create_timestamp';
|
||||
$insertValues[] = ':server_create_timestamp';
|
||||
$bindParams[':server_create_timestamp'] = time();
|
||||
|
||||
$insertFields[] = 'server_modified_timestamp';
|
||||
$insertValues[] = ':server_modified_timestamp';
|
||||
$bindParams[':server_modified_timestamp'] = time();
|
||||
|
||||
$query = "INSERT INTO servers (" . implode(',', $insertFields) . ")
|
||||
VALUES (" . implode(',', $insertValues) . ")
|
||||
ON DUPLICATE KEY UPDATE ";
|
||||
|
||||
# Build the ON DUPLICATE KEY UPDATE, only foor fields that exist
|
||||
$updateParts = [];
|
||||
foreach ($insertFields as $field) {
|
||||
if (!in_array($field, ['server_create_timestamp', 'server_uuid'])) {
|
||||
$updateParts[] = "$field = VALUES($field)";
|
||||
}
|
||||
}
|
||||
$query .= implode(", ", $updateParts);
|
||||
|
||||
$stmt = $GLOBALS['pdo']->prepare($query);
|
||||
|
||||
if (!$stmt->execute($bindParams)) {
|
||||
$this->apiOutput(400, ['error' => "Failed to insert server into database"]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function validateLicenseData($server_vm_id, $server_licenses)
|
||||
{
|
||||
$server_vm_id = $this->validateSingleData($server_vm_id, ['type' => 'string']);
|
||||
$server_licenses_posted = $this->validateSingleData($server_licenses, ['type' => 'array']);
|
||||
|
||||
$query = "SELECT server_licenses FROM servers WHERE server_vm_id = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $server_vm_id);
|
||||
$this->executeStatement($stmt);
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$server_licenses_db = $result->fetch_assoc();
|
||||
|
||||
$server_licenses_db = $server_licenses_db['server_licenses'] ?? null;
|
||||
$server_licenses_db_new = [];
|
||||
if (!empty($server_licenses_db)) {
|
||||
$decoded = json_decode($server_licenses_db, true);
|
||||
if (is_array($decoded)) {
|
||||
foreach ($decoded as $item) {
|
||||
foreach ($item as $key => $value) {
|
||||
$server_licenses_db_new[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($server_licenses_posted as $item) {
|
||||
foreach ($item as $rawKey => $value) {
|
||||
|
||||
$prefix = substr($rawKey, 0, 1);
|
||||
$license = substr($rawKey, 1);
|
||||
|
||||
if ($prefix === '+') {
|
||||
$server_licenses_db_new[$license] = $value;
|
||||
}
|
||||
|
||||
if ($prefix === '-') {
|
||||
unset($server_licenses_db_new[$license]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$server_licenses_db_new_final = [];
|
||||
foreach ($server_licenses_db_new as $key => $value) {
|
||||
$server_licenses_db_new_final[] = [$key => $value];
|
||||
}
|
||||
|
||||
return empty($server_licenses_db_new_final) ? '[]' : json_encode($server_licenses_db_new_final);
|
||||
}
|
||||
|
||||
private function validateBackupData($server_vm_id, $server_backup)
|
||||
{
|
||||
$server_vm_id = $this->validateSingleData($server_vm_id, ['type' => 'string']);
|
||||
$server_backup_posted = $this->validateSingleData($server_backup, ['type' => 'array']);
|
||||
|
||||
$query = "SELECT server_backup FROM servers WHERE server_vm_id = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $server_vm_id);
|
||||
$this->executeStatement($stmt);
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$server_backup_db = $result->fetch_assoc();
|
||||
|
||||
$server_backup_db = $server_backup_db['server_backup'] ?? null;
|
||||
$server_backup_db_new = [];
|
||||
if (!empty($server_backup_db)) {
|
||||
$decoded = json_decode($server_backup_db, true);
|
||||
if (is_array($decoded)) {
|
||||
foreach ($decoded as $item) {
|
||||
foreach ($item as $key => $value) {
|
||||
$server_backup_db_new[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($server_backup_posted as $item) {
|
||||
foreach ($item as $rawKey => $value) {
|
||||
|
||||
$prefix = substr($rawKey, 0, 1);
|
||||
$backup = substr($rawKey, 1);
|
||||
|
||||
if ($prefix === '+') {
|
||||
$server_backup_db_new[$backup] = $value;
|
||||
}
|
||||
|
||||
if ($prefix === '-') {
|
||||
unset($server_backup_db_new[$backup]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$server_backup_db_new_final = [];
|
||||
foreach ($server_backup_db_new as $key => $value) {
|
||||
$server_backup_db_new_final[] = [$key => $value];
|
||||
}
|
||||
|
||||
return empty($server_backup_db_new_final) ? '[]' : json_encode($server_backup_db_new_final);
|
||||
}
|
||||
|
||||
public function processServerData($server, $requiredFields, $optionalFields)
|
||||
{
|
||||
// since the disk data is sent as an array we need to check it seperatly from the other data validations
|
||||
|
||||
if (!empty($server['server_disks']) && is_array($server['server_disks'])) {
|
||||
$server['server_disks'] = $this->validateDiskData($server['server_disks']);
|
||||
} else {
|
||||
unset($server['server_disks']);
|
||||
}
|
||||
|
||||
if (!empty($server['server_licenses']) && is_array($server['server_licenses'])) {
|
||||
$server['server_licenses'] = $this->validateLicenseData($server['server_vm_id'], $server['server_licenses']);
|
||||
} else {
|
||||
unset($server['server_licenses']);
|
||||
}
|
||||
|
||||
if (!empty($server['server_backup']) && is_array($server['server_backup'])) {
|
||||
$server['server_backup'] = $this->validateBackupData($server['server_vm_id'], $server['server_backup']);
|
||||
} else {
|
||||
unset($server['server_backup']);
|
||||
}
|
||||
|
||||
foreach (['server_ipv4', 'server_ipv6'] as $key) {
|
||||
if (!empty($server[$key]) && is_array($server[$key])) {
|
||||
$server[$key] = json_encode($server[$key]);
|
||||
} else {
|
||||
unset($server[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->postedData = $server;
|
||||
|
||||
$this->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$this->updateServer();
|
||||
}
|
||||
|
||||
public function deleteServer()
|
||||
{
|
||||
$query = "DELETE FROM servers WHERE server_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['server_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$this->apiOutput(200, ['success' => 'Server removed']);
|
||||
}
|
||||
}
|
||||
34
pub/api/classes/API_system_modules.php
Normal file
34
pub/api/classes/API_system_modules.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_system_modules extends API
|
||||
{
|
||||
public function getModules($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('system_modules');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'Permission');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function enableModule()
|
||||
{
|
||||
|
||||
$module_uuid_enabled = ($this->data['module_enabled']) ? 0 : 1;
|
||||
|
||||
# Module 'system cannot be disabled'
|
||||
$query = "UPDATE system_modules SET module_enabled = ? WHERE module_uuid = ? AND module_slugify != 'system'";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('is', $module_uuid_enabled, $this->data['module_uuid']);
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Module ' . ($module_uuid_enabled ? 'enabled' : 'disabled') . ' successfully.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
pub/api/classes/API_system_sources.php
Normal file
26
pub/api/classes/API_system_sources.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_system_sources extends API
|
||||
{
|
||||
public function inserveUpdate()
|
||||
{
|
||||
$query = "INSERT INTO system_sources (source_uuid, source_name, source_url, source_auth_username, source_auth_password, source_auth_token, source_create_timestamp, source_modified_timestamp)
|
||||
VALUES (UUID(), ?, ?, '', '', ?, ?, NULL)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
source_url = VALUES(source_url),
|
||||
source_auth_token = VALUES(source_auth_token),
|
||||
source_modified_timestamp = VALUES(source_create_timestamp)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('sssi', $this->data['source_name'], $this->data['source_url'], $this->data['source_auth_token'], time());
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$this->apiOutput(200, ['success' => 'Information modified'], 'Information updated successfully.');
|
||||
}
|
||||
}
|
||||
140
pub/api/classes/API_usergroups.php
Normal file
140
pub/api/classes/API_usergroups.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_usergroups extends API
|
||||
{
|
||||
public function getUsergroup($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('vc_user_groups');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'User Group');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function createUsergroups()
|
||||
{
|
||||
# check if the user_group already exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_group_slugify', 1 => $this->data['user_group_slugify']]]];
|
||||
|
||||
if ($this->getUsergroup(true)) {
|
||||
$this->apiOutput(409, ['error' => 'Usergroup already exists.']);
|
||||
}
|
||||
|
||||
$this->data['user_group_weight'] = $this->get_next_available_user_group_weight($this->data['user_group_weight']);
|
||||
|
||||
if ($this->data['user_group_weight'] < $_SESSION['user']['user_group_weight']) {
|
||||
$this->apiOutput(400, ['error' => 'You cannot make an group with an lower weight then yourself!']);
|
||||
}
|
||||
|
||||
$query = "INSERT INTO vc_user_groups (user_group_uuid, user_group_name, user_group_slugify, user_group_weight, user_group_type, user_group_create_timestamp) VALUES (UUID(), ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssisi", $this->data['user_group_name'], $this->data['user_group_slugify'], $this->data['user_group_weight'], $this->data['user_group_type'], time());
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
$user_group = $this->getUsergroup();
|
||||
$user_group_uuid = $user_group[0]['user_group_uuid'];
|
||||
|
||||
|
||||
# Get all the permission from the database and create the permission for the user group.
|
||||
$stmt = $this->conn->query("SELECT permission_uuid FROM vc_permissions");
|
||||
while ($row = $stmt->fetch_assoc()) {
|
||||
$permission_uuids[] = $row['permission_uuid'];
|
||||
}
|
||||
|
||||
|
||||
$values = [];
|
||||
foreach ($permission_uuids as $permission_uuid) {
|
||||
$permission_uuid_safe = $GLOBALS['conn']->real_escape_string($permission_uuid);
|
||||
$values[] = "('$permission_uuid_safe', '$user_group_uuid')";
|
||||
}
|
||||
|
||||
if (!empty($values)) {
|
||||
$values_sql = implode(", ", $values);
|
||||
|
||||
$query = "INSERT INTO vc_user_group_permissions_portal (permission_uuid, user_group_uuid) VALUES $values_sql";
|
||||
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'User group created successfully']);
|
||||
} else {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the user-group.'], 'error_contact_support');
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteUsergroup()
|
||||
{
|
||||
# check if the user group exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_group_uuid', 1 => $this->data['user_group_uuid']]]];
|
||||
$user_group = $this->getUsergroup();
|
||||
|
||||
# superuser cannot be deleted
|
||||
if ($user_group[0]['user_group_slufigy'] === 'superuser') {
|
||||
$this->apiOutput(400, ['error' => 'superuser cannot be deleted.']);
|
||||
}
|
||||
|
||||
if ($user_group[0]['user_group_weight'] < $_SESSION['user']['user_group_weight']) {
|
||||
$this->apiOutput(400, ['error' => 'groups with an lower weight cannot be deleted.']);
|
||||
}
|
||||
|
||||
$query = "DELETE FROM vc_user_groups WHERE user_group_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['user_group_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'User group created deleted']);
|
||||
}
|
||||
|
||||
private function get_next_available_user_group_weight($weight)
|
||||
{
|
||||
# checks what the next avail weight is if the weight is taken by another item
|
||||
$sql = "SELECT user_group_weight FROM vc_user_groups ORDER BY user_group_weight ASC";
|
||||
$result = $this->conn->query($sql);
|
||||
|
||||
// Store all existing weights in an array
|
||||
$existing_weights = [];
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$existing_weights[] = (int)$row['user_group_weight'];
|
||||
}
|
||||
|
||||
// If weight already exists, find the next available integer
|
||||
while (in_array($weight, $existing_weights)) {
|
||||
$weight++;
|
||||
}
|
||||
|
||||
return $weight;
|
||||
}
|
||||
|
||||
public function updateUserGroup()
|
||||
{
|
||||
# check if the user group exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_group_uuid', 1 => $this->data['user_group_uuid']]]];
|
||||
$user_group = $this->getUsergroup();
|
||||
|
||||
# superuser cannot be modified
|
||||
if ($user_group[0]['user_group_slufigy'] === 'superuser') {
|
||||
$this->apiOutput(500, ['error' => 'superuser cannot be modified']);
|
||||
}
|
||||
|
||||
if ($user_group[0]['user_group_weight'] != $this->data['user_group_weight']) {
|
||||
$this->data['user_group_weight'] = $this->get_next_available_user_group_weight($this->data['user_group_weight']);
|
||||
}
|
||||
|
||||
if ($this->data['user_group_weight'] < $_SESSION['user']['user_group_weight']) {
|
||||
$this->apiOutput(400, ['error' => 'You cannot make an group with an lower weight then yourself!']);
|
||||
}
|
||||
|
||||
$query = "UPDATE vc_user_groups SET user_group_name = ?, user_group_weight = ?, user_group_modified_timestamp = ? WHERE user_group_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("siis", $this->data['user_group_name'], $this->data['user_group_weight'], time(), $this->data['user_group_uuid']);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'User group created updated']);
|
||||
}
|
||||
}
|
||||
151
pub/api/classes/API_users.php
Normal file
151
pub/api/classes/API_users.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
use api\classes\API_usergroups;
|
||||
use bin\php\Classes\mailBuilder;
|
||||
|
||||
require_once 'API.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/Classes/mailBuilder.php';
|
||||
|
||||
class API_users extends API
|
||||
{
|
||||
public function getUser($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('vc_users');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'User');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function createUser()
|
||||
{
|
||||
# check if the user already exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_email', 1 => $this->data['user_email']]]];
|
||||
|
||||
if ($this->getUser(true)) {
|
||||
$this->apiOutput(409, ['error' => 'user already exists.']);
|
||||
}
|
||||
|
||||
|
||||
if ($this->getUserGroupWeight() < $_SESSION['user']['user_group_weight']) {
|
||||
$this->apiOutput(400, ['error' => 'You cannot make an user with an lower weight then yourself!']);
|
||||
}
|
||||
|
||||
$query = "INSERT INTO vc_users (
|
||||
user_uuid, user_group_uuid, user_email, user_first_name, user_last_name, user_full_name,
|
||||
user_phone_number, user_password, user_password_reset_token, user_password_reset_expires,
|
||||
user_two_factor_enabled, user_two_factor_secret, user_status,
|
||||
user_verified_email, user_verified_phone, user_create_timestamp, user_modified_timestamp,
|
||||
user_last_login_timestamp, user_login_attempts, user_pref_language, user_stompable
|
||||
) VALUES (
|
||||
UUID(), ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, NULL, ?, 0, 0, ?, NULL, NULL, 0, ?, 0
|
||||
)";
|
||||
|
||||
$stmt = $this->prepareStatement($query);
|
||||
|
||||
$stmt->bind_param("ssssssssisis",
|
||||
$this->data['user_group_uuid'],
|
||||
$this->data['user_email'],
|
||||
$this->data['user_first_name'],
|
||||
$this->data['user_last_name'],
|
||||
$this->data['user_full_name'],
|
||||
$this->data['user_phone_number'],
|
||||
$this->data['user_password'],
|
||||
$this->data['user_password_reset_token'],
|
||||
$this->data['user_password_reset_expires'],
|
||||
$this->data['user_status'],
|
||||
time(),
|
||||
$this->data['user_pref_language'],
|
||||
);
|
||||
|
||||
# Sending an email to the user
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$verifyLink = "https://{$host}/login/verifyEmail.php?token={$this->data['user_password_reset_token']}";
|
||||
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$mail = new mailBuilder();
|
||||
$mail->subject = "Hello " . $this->data['user_first_name'] . ", your Sentri account is ready — set your password";
|
||||
$mail->addAddress($this->data['user_email'], $this->data['user_first_name']);
|
||||
$mail->mailText = '
|
||||
Hello ' . $this->data['user_first_name'] . ',<br><br>
|
||||
An account has been created for you in Sentri.<br>
|
||||
To activate your account, please verify your email address and set your password by clicking the link below:<br>
|
||||
<a href="' . $verifyLink . '" class="btn btn-primary">Activate My Account</a><br><br>
|
||||
Or copy and paste the following link into your browser: <br>' . $verifyLink . '<br><br>
|
||||
|
||||
This link is valid for 24 hours.<br>
|
||||
After that, you’ll need to request a new activation link.<br><br>
|
||||
|
||||
If you weren’t expecting this email or believe it was sent by mistake, you can safely ignore it.<br><br>
|
||||
|
||||
Best regards,<br><br>
|
||||
The Sentri gnomes';
|
||||
$mail->sendMail();
|
||||
|
||||
$this->apiOutput(200, ['success' => 'User created successfully. mail has been sent']);
|
||||
}
|
||||
|
||||
private function getUserGroupWeight()
|
||||
{
|
||||
require_once 'API_usergroups.php';
|
||||
|
||||
$API_usergroups = new API_usergroups();
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_group_uuid', 1 => $this->data['user_group_uuid']]]];
|
||||
|
||||
return $API_usergroups->getUserGroup()[0]['user_group_weight'];
|
||||
}
|
||||
|
||||
public function updateUser()
|
||||
{
|
||||
# check if the user exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $this->data['user_uuid']]]];
|
||||
$this->getUser();
|
||||
|
||||
if ($this->getUserGroupWeight() < $_SESSION['user']['user_group_weight']) {
|
||||
$this->apiOutput(400, ['error' => 'You cannot edit a user with an lower weight then yourself!']);
|
||||
}
|
||||
|
||||
$query = "UPDATE vc_users SET user_group_uuid = ?, user_email = ?, user_first_name = ?, user_last_name = ?, user_full_name = ?, user_phone_number = ?, user_status = ?, user_pref_language = ?, user_modified_timestamp = ?, user_stompable = ? WHERE user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssssssssiis', $this->data['user_group_uuid'], $this->data['user_email'], $this->data['user_first_name'], $this->data['user_last_name'], $this->data['user_full_name'], $this->data['user_phone_number'], $this->data['user_status'], $this->data['user_pref_language'], time(), $this->data['user_stompable'], $this->data['user_uuid']);
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'User successfully updated.']);
|
||||
}
|
||||
|
||||
public function deleteUser()
|
||||
{
|
||||
# delete an user
|
||||
|
||||
# chect if the user exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $this->data['user_uuid']]]];
|
||||
$user_data = $this->getUser()[0];
|
||||
|
||||
|
||||
$this->data['user_group_uuid'] = $user_data['user_group_uuid'];
|
||||
|
||||
# check group weigth
|
||||
if ($this->getUserGroupWeight() < $_SESSION['user']['user_group_weight']) {
|
||||
$this->apiOutput(400, ['error' => 'You cannot delete a user with an lower weight then yourself!']);
|
||||
}
|
||||
|
||||
if ($user_data['user_uuid'] == $_SESSION['user']['user_uuid']) {
|
||||
$this->apiOutput(400, ['error' => 'You cannot delete yourself, maybe some rope will do.']);
|
||||
}
|
||||
|
||||
|
||||
$query = "DELETE FROM vc_users WHERE user_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('s', $this->data['user_uuid']);
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
$this->apiOutput(200, ['success' => 'User successfully deleted']);
|
||||
}
|
||||
}
|
||||
45
pub/api/classes/API_usersavatar.php
Normal file
45
pub/api/classes/API_usersavatar.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
use api\classes\imageProcessor;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_usersavatar extends API
|
||||
{
|
||||
|
||||
public function createUserImage($imageRestrictions)
|
||||
{
|
||||
try {
|
||||
# Main image
|
||||
$imageProcessor = new imageProcessor('user_profile_picture');
|
||||
$imageProcessor->imageRestrictions = $imageRestrictions;
|
||||
$imageProcessor->validateAndProcess();
|
||||
$ImageData = $imageProcessor->returnBase64image();
|
||||
} catch (Exception $e) {
|
||||
$this->apiOutput(401, ['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
return $ImageData;
|
||||
}
|
||||
|
||||
public function updateUserImage()
|
||||
{
|
||||
$query = "UPDATE vc_users SET
|
||||
user_profile_picture = ?,
|
||||
user_profile_picture_thumbnail = ?
|
||||
WHERE user_uuid = ?";
|
||||
|
||||
$stmt = $stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("sss",
|
||||
$this->data['user_profile_picture'],
|
||||
$this->data['user_profile_picture_thumbnail'],
|
||||
$this->data['user_uuid']
|
||||
);
|
||||
$this->executeStatement($stmt);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
71
pub/api/classes/API_vendors.php
Normal file
71
pub/api/classes/API_vendors.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace api\classes;
|
||||
|
||||
use api\classes\API;
|
||||
|
||||
require_once 'API.php';
|
||||
|
||||
class API_vendors extends API
|
||||
{
|
||||
public function getVendors($returnBoolean = false)
|
||||
{
|
||||
list($query, $types, $params) = $this->buildDynamicQuery('vc_vendors');
|
||||
|
||||
$items = $this->generalGetFunction($query, $types, $params, $returnBoolean, 'Vendor');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function createVendor()
|
||||
{
|
||||
if (isset($this->data['vendor_image'])) {
|
||||
$query = "INSERT INTO vc_vendors (vendor_uuid, vendor_name, vendor_slugify, vendor_description, vendor_enabled, vendor_create_timestamp, vendor_image) VALUES (UUID(), ?, ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssssis', $this->data['vendor_name'], $this->data['vendor_slugify'], $this->data['vendor_description'], $this->data['vendor_enabled'], time(), $this->data['vendor_image']);
|
||||
} else {
|
||||
$query = "INSERT INTO vc_vendors (vendor_uuid, vendor_name, vendor_slugify, vendor_description, vendor_enabled, vendor_create_timestamp) VALUES (UUID(), ?, ?, ?, ?, ?)";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param('ssssi', $this->data['vendor_name'], $this->data['vendor_slugify'], $this->data['vendor_description'], $this->data['vendor_enabled'], time());
|
||||
}
|
||||
|
||||
$this->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
|
||||
$result = $this->getVendorSlugify();
|
||||
if ($result->num_rows === 0) {
|
||||
$this->apiOutput(500, ['error' => 'Something went wrong creating the vendor on the server.'], 'error_contact_support');
|
||||
}
|
||||
|
||||
$platform_data = $result->fetch_assoc();
|
||||
|
||||
$this->apiOutput(200, ['success' => $platform_data], 'item_added');
|
||||
}
|
||||
|
||||
public function getVendorSlugify()
|
||||
{
|
||||
$query = "SELECT * FROM vc_vendors WHERE vendor_slugify = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("s", $this->data['vendor_slugify']);
|
||||
$this->executeStatement($stmt);
|
||||
return $stmt->get_result();
|
||||
}
|
||||
|
||||
public function editVendor()
|
||||
{
|
||||
if (isset($this->data['vendor_image'])) {
|
||||
$query = "UPDATE vc_vendors SET vendor_name = ?, vendor_description = ?, vendor_enabled = ?, vendor_image = ?, vendor_modified_timestamp = ? WHERE vendor_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssisis", $this->data['vendor_name'], $this->data['vendor_description'], $this->data['vendor_enabled'], $this->data['vendor_image'], time(), $this->data['vendor_uuid']);
|
||||
} else {
|
||||
$query = "UPDATE vc_vendors SET vendor_name = ?, vendor_description = ?, vendor_enabled = ?, vendor_modified_timestamp = ? WHERE vendor_uuid = ?";
|
||||
$stmt = $this->prepareStatement($query);
|
||||
$stmt->bind_param("ssiis", $this->data['vendor_name'], $this->data['vendor_description'], $this->data['vendor_enabled'], time(), $this->data['vendor_uuid']);
|
||||
}
|
||||
|
||||
if ($this->executeStatement($stmt)) {
|
||||
$this->apiOutput(200, ['success' => 'Platform updated successfully.']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
202
pub/api/classes/imageProcessor.php
Normal file
202
pub/api/classes/imageProcessor.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace api\classes;
|
||||
class imageProcessor
|
||||
{
|
||||
public $postedFile = null;
|
||||
private $imageTmpPath;
|
||||
private $imageInfo;
|
||||
|
||||
public $imageRestrictions = [
|
||||
'min_width' => 100,
|
||||
'max_width' => 600,
|
||||
'min_height' => 100,
|
||||
'max_height' => 600,
|
||||
'square' => false,
|
||||
'allowed_types' => ['image/png', 'image/jpeg', 'image/webp'],
|
||||
'max_size_kb' => 2048, // 2MB
|
||||
'transparent' => false
|
||||
];
|
||||
|
||||
private $finalImage = null;
|
||||
|
||||
public function __construct($imageName)
|
||||
{
|
||||
if (isset($_FILES[$imageName]) && $_FILES[$imageName]['error'] === UPLOAD_ERR_OK) {
|
||||
$this->postedFile = $_FILES[$imageName];
|
||||
$this->imageTmpPath = $this->postedFile['tmp_name'];
|
||||
$this->imageInfo = getimagesize($this->imageTmpPath);
|
||||
} elseif (isset($_POST['image_base64'])) {
|
||||
$base64 = $_POST['image_base64'];
|
||||
|
||||
if (preg_match('/^data:(image\/\w+);base64,/', $base64, $matches)) {
|
||||
$mimeType = $matches[1];
|
||||
$base64 = substr($base64, strpos($base64, ',') + 1);
|
||||
} else {
|
||||
throw new Exception('Invalid image data.');
|
||||
}
|
||||
|
||||
$imageData = base64_decode($base64);
|
||||
if ($imageData === false) {
|
||||
throw new Exception('Invalid base64 image data.');
|
||||
}
|
||||
|
||||
# Create image directly from string (no file)
|
||||
$srcImage = imagecreatefromstring($imageData);
|
||||
if (!$srcImage) {
|
||||
throw new Exception('Failed to create image from string.');
|
||||
}
|
||||
|
||||
# Now you can get dimensions directly
|
||||
$width = imagesx($srcImage);
|
||||
$height = imagesy($srcImage);
|
||||
|
||||
# Store $srcImage in a class property, continue processing in-memory
|
||||
$this->imageResource = $srcImage;
|
||||
$this->imageInfo = [
|
||||
'mime' => $mimeType,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'size' => strlen($imageData)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function validateAndProcess()
|
||||
{
|
||||
if (!$this->postedFile) {
|
||||
return true;
|
||||
}
|
||||
$width = $this->imageInfo[0];
|
||||
$height = $this->imageInfo[1];
|
||||
$mime = $this->imageInfo['mime'];
|
||||
$fileSizeKB = filesize($this->imageTmpPath) / 1024;
|
||||
|
||||
if (!in_array($mime, $this->imageRestrictions['allowed_types'])) {
|
||||
throw new Exception("Invalid image type: $mime");
|
||||
}
|
||||
|
||||
if ($fileSizeKB > $this->imageRestrictions['max_size_kb']) {
|
||||
throw new Exception("Image exceeds max file size.");
|
||||
}
|
||||
|
||||
# Resize to fit within min/max bounds
|
||||
$resizedImage = $this->resizeToFitRestrictions($mime, $width, $height);
|
||||
|
||||
# Optionally square it
|
||||
if ($this->imageRestrictions['square']) {
|
||||
$resizedImage = $this->makeImageSquare($resizedImage, $mime);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
imagejpeg($resizedImage);
|
||||
break;
|
||||
case 'image/png':
|
||||
imagepng($resizedImage);
|
||||
break;
|
||||
case 'image/webp':
|
||||
imagewebp($resizedImage);
|
||||
break;
|
||||
}
|
||||
$this->finalImage = ob_get_clean();
|
||||
|
||||
imagedestroy($resizedImage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function mimeSupportsTransparency($mime)
|
||||
{
|
||||
return in_array($mime, ['image/png', 'image/webp']);
|
||||
}
|
||||
|
||||
private function setTransparentCanvas($image, $width, $height)
|
||||
{
|
||||
// Enable alpha blending and preserve alpha channel
|
||||
imagealphablending($image, false);
|
||||
imagesavealpha($image, true);
|
||||
|
||||
// Fill the image with a fully transparent color
|
||||
$transparent = imagecolorallocatealpha($image, 0, 0, 0, 127);
|
||||
imagefilledrectangle($image, 0, 0, $width, $height, $transparent);
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
private function resizeToFitRestrictions($mime, $width, $height)
|
||||
{
|
||||
$minW = $this->imageRestrictions['min_width'];
|
||||
$maxW = $this->imageRestrictions['max_width'];
|
||||
$minH = $this->imageRestrictions['min_height'];
|
||||
$maxH = $this->imageRestrictions['max_height'];
|
||||
|
||||
$srcImage = match ($mime) {
|
||||
'image/jpeg' => imagecreatefromjpeg($this->imageTmpPath),
|
||||
'image/png' => imagecreatefrompng($this->imageTmpPath),
|
||||
'image/webp' => imagecreatefromwebp($this->imageTmpPath),
|
||||
default => throw new Exception("Unsupported image type.")
|
||||
};
|
||||
|
||||
# Determine new size
|
||||
$newWidth = $width;
|
||||
$newHeight = $height;
|
||||
|
||||
if ($width < $minW || $width > $maxW || $height < $minH || $height > $maxH) {
|
||||
# Calculate scale factor based on limits
|
||||
$widthScale = ($width < $minW) ? $minW / $width : ($width > $maxW ? $maxW / $width : 1);
|
||||
$heightScale = ($height < $minH) ? $minH / $height : ($height > $maxH ? $maxH / $height : 1);
|
||||
|
||||
# Use the smallest scale to ensure both dimensions fit
|
||||
$scale = min($widthScale, $heightScale);
|
||||
|
||||
$newWidth = round($width * $scale);
|
||||
$newHeight = round($height * $scale);
|
||||
}
|
||||
|
||||
$resizedImage = imagecreatetruecolor($newWidth, $newHeight);
|
||||
|
||||
# keep transparent
|
||||
if ($this->mimeSupportsTransparency($mime)) {
|
||||
$this->setTransparentCanvas($resizedImage, $newWidth, $newHeight);
|
||||
}
|
||||
|
||||
imagecopyresampled($resizedImage, $srcImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
|
||||
imagedestroy($srcImage);
|
||||
return $resizedImage;
|
||||
}
|
||||
|
||||
private function makeImageSquare($srcImage, $mime)
|
||||
{
|
||||
$width = imagesx($srcImage);
|
||||
$height = imagesy($srcImage);
|
||||
|
||||
$size = min($width, $height);
|
||||
$x = ($width - $size) / 2;
|
||||
$y = ($height - $size) / 2;
|
||||
|
||||
$squareImage = imagecreatetruecolor($size, $size);
|
||||
|
||||
# keep transparent
|
||||
if ($this->mimeSupportsTransparency($mime)) {
|
||||
$this->setTransparentCanvas($squareImage, $size, $size);
|
||||
}
|
||||
|
||||
imagecopyresampled($squareImage, $srcImage, 0, 0, $x, $y, $size, $size, $size, $size);
|
||||
imagedestroy($srcImage);
|
||||
|
||||
return $squareImage;
|
||||
}
|
||||
|
||||
public function returnBase64image()
|
||||
{
|
||||
if ($this->finalImage) {
|
||||
return base64_encode($this->finalImage);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
41
pub/api/v1/access-rights/index.php
Normal file
41
pub/api/v1/access-rights/index.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_permissions;
|
||||
use api\classes\API_usergroups;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_permissions.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_usergroups.php';
|
||||
|
||||
$API_permissions = new API_permissions();
|
||||
$API_usergroups = new API_usergroups();
|
||||
|
||||
if ($API_permissions->request_method === 'GET') {
|
||||
# to be made, get all the access-rights and implement the builder
|
||||
|
||||
} elseif ($API_permissions->request_method === 'PUT') {
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_permissions->return_url = false;
|
||||
|
||||
$API_permissions->checkPermissions('admin-access-control-permissions', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'permission_uuid' => ['type' => 'uuid'],
|
||||
'user_group_uuid' => ['type' => 'uuid'],
|
||||
'permission_value' => ['type' => 'enum', 'values' => ['NA', 'RO', 'RW']],
|
||||
];
|
||||
|
||||
$API_permissions->validateData($requiredFields);
|
||||
|
||||
# check if the permission exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'permission_uuid', 1 => $API_permissions->data['permission_uuid']]]];
|
||||
$API_permissions->getPermission();
|
||||
|
||||
# check if the user_group_uuid exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_group_uuid', 1 => $API_permissions->data['user_group_uuid']]]];
|
||||
$API_usergroups->getUsergroup();
|
||||
|
||||
# Update the permission
|
||||
$API_permissions->updateAccessRights();
|
||||
}
|
||||
29
pub/api/v1/customers/companies/activate/index.php
Normal file
29
pub/api/v1/customers/companies/activate/index.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_companies;
|
||||
|
||||
session_start();
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_companies.php';
|
||||
|
||||
|
||||
# Check permissions
|
||||
$API_companies = new API_companies();
|
||||
|
||||
|
||||
if ($API_companies->request_method === 'PUT') {
|
||||
$API_companies->checkPermissions('customer-companies', 'RW');
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_companies->return_url = false;
|
||||
|
||||
$requiredFields = [
|
||||
'company_uuid' => ['type' => 'uuid'],
|
||||
'company_state' => ['type' => 'enum', 'values' => ['active', 'imported', 'orphaned']]
|
||||
];
|
||||
|
||||
$API_companies->validateData($requiredFields);
|
||||
|
||||
$API_companies->updateCompanyState();
|
||||
|
||||
}
|
||||
66
pub/api/v1/customers/companies/sync/index.php
Normal file
66
pub/api/v1/customers/companies/sync/index.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_inserve;
|
||||
|
||||
session_start();
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_inserve.php';
|
||||
|
||||
$API_inserve = new API_inserve();
|
||||
$API_inserve->setupConnection();
|
||||
|
||||
if ($API_inserve->request_method === 'POST') {
|
||||
# Code below will retrieve all the companies and create or update it in the database
|
||||
#
|
||||
|
||||
$API_inserve->checkPermissions('customer-companies', 'RW');
|
||||
|
||||
$allCompanies = [];
|
||||
$page = 1;
|
||||
|
||||
do {
|
||||
$result = $API_inserve->companies($page);
|
||||
|
||||
if (!isset($result['data']) || empty($result['data'])) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($result['data'] as $item) {
|
||||
$allCompanies[] = [
|
||||
'id' => $item['id'],
|
||||
'name' => $item['name'],
|
||||
'debtor_code' => $item['debtor_code'],
|
||||
'archived_at' => $item['archived_at']
|
||||
];
|
||||
}
|
||||
|
||||
$page++;
|
||||
|
||||
} while ($result['next_page_url'] !== null);
|
||||
|
||||
foreach ($allCompanies as $company) {
|
||||
$source_uuid = $API_inserve->inserve_source_uuid;
|
||||
$company_id = $company['id'];
|
||||
$debtor_code = $company['debtor_code'];
|
||||
$company_name = $company['name'];
|
||||
$created_at = time();
|
||||
|
||||
# Add or modify the company if it is not archived
|
||||
if ($company['archived_at'] == null) {
|
||||
$query = "INSERT INTO companies (source_uuid, company_source_id, company_source_id2, company_name, company_create_timestamp)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
company_name = VALUES(company_name),
|
||||
company_source_id2 = VALUES(company_source_id2),
|
||||
company_modified_timestamp = VALUES(company_create_timestamp)";
|
||||
$stmt = $API_inserve->prepareStatement($query);
|
||||
$stmt->bind_param('ssssi', $source_uuid, $company_id, $debtor_code, $company_name, $created_at);
|
||||
$API_inserve->executeStatement($stmt);
|
||||
$stmt->close();
|
||||
}
|
||||
}
|
||||
|
||||
$API_inserve->apiOutput(200, ['success' => 'Sync is done successfully']);
|
||||
}
|
||||
|
||||
|
||||
118
pub/api/v1/devices/files/index.php
Normal file
118
pub/api/v1/devices/files/index.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_devices;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_devices.php';
|
||||
|
||||
$API_devices = new API_devices();
|
||||
|
||||
if ($API_devices->request_method === 'POST') {
|
||||
|
||||
$API_devices->checkPermissions('admin-devices-files', 'RW');
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_devices->return_url = false;
|
||||
|
||||
$device_slugify = isset($_POST['device_slugify']) ? preg_replace('/[^a-zA-Z0-9_-]/', '_', $_POST['device_slugify']) : '';
|
||||
$filetype = $_POST['filetype'] ?? '';
|
||||
|
||||
$allowedFiletypes = ['documents' => 'pdf', 'firmware' => 'rom'];
|
||||
if (!array_key_exists($filetype, $allowedFiletypes)) {
|
||||
$API_devices->apiOutput(400, ['error' => 'Invalid file type']);
|
||||
}
|
||||
|
||||
if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
|
||||
$API_devices->apiOutput(400, ['error' => 'No file uploaded or upload error']);
|
||||
}
|
||||
|
||||
$filename = basename($_FILES['file']['name']);
|
||||
$filename = preg_replace('/[^a-zA-Z0-9_\.\-]/', '_', $filename);
|
||||
$file_extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
|
||||
$expectedExtension = $allowedFiletypes[$filetype];
|
||||
if ($file_extension !== $expectedExtension) {
|
||||
$API_devices->apiOutput(415, ['error' => "Invalid file extension. Expected: $expectedExtension"]);
|
||||
}
|
||||
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$detectedMime = finfo_file($finfo, $_FILES['file']['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
$expectedMimeTypes = [
|
||||
'pdf' => 'application/pdf',
|
||||
'rom' => 'application/octet-stream'
|
||||
];
|
||||
|
||||
if (!str_starts_with($detectedMime, $expectedMimeTypes[$expectedExtension])) {
|
||||
$API_devices->apiOutput(415, ['error' => 'Invalid MIME type: ' . $detectedMime]);
|
||||
}
|
||||
|
||||
$destination_dir = $_SERVER['DOCUMENT_ROOT'] . '/data/devices/' . $device_slugify . '/' . $filetype;
|
||||
if (!is_dir($destination_dir) && !mkdir($destination_dir, 0775, true) && !is_dir($destination_dir)) {
|
||||
$API_devices->apiOutput(500, ['error' => 'Failed to create directory']);
|
||||
}
|
||||
|
||||
|
||||
$destination = $destination_dir . '/' . $filename;
|
||||
if (file_exists($destination)) {
|
||||
$API_devices->apiOutput(409, ['error' => 'File already exists']);
|
||||
}
|
||||
|
||||
if (move_uploaded_file($_FILES['file']['tmp_name'], $destination)) {
|
||||
chmod($destination, 0644); // Set safe permissions
|
||||
$API_devices->apiOutput(200, ['success' => 'File uploaded succcessfully']);
|
||||
} else {
|
||||
$API_devices->apiOutput(500, ['error' => 'Failed to move uploaded file']);
|
||||
}
|
||||
|
||||
} elseif ($API_devices->request_method === 'DELETE') {
|
||||
|
||||
$API_devices->checkPermissions('admin-devices-files', 'RW');
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_devices->return_url = false;
|
||||
|
||||
$relativePath = $_POST['file_name'] ?? '';
|
||||
|
||||
// Ensure it's not empty and doesn't contain null byte or backslashes
|
||||
if (empty($relativePath) || str_contains($relativePath, "\0") || str_contains($relativePath, '\\')) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid path input']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Normalize base root
|
||||
$root = realpath($_SERVER['DOCUMENT_ROOT'] . '/data/devices');
|
||||
if (!$root) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid devices root']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Resolve full path
|
||||
$requestedPath = realpath($_SERVER['DOCUMENT_ROOT'] . $relativePath);
|
||||
|
||||
// Validate resolved path
|
||||
if (!$requestedPath || strpos($requestedPath, $root) !== 0) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Access denied']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if file exists and is a regular file
|
||||
if (!is_file($requestedPath)) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['status' => 'error', 'message' => 'File does not exist']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Attempt to delete
|
||||
if (unlink($requestedPath)) {
|
||||
echo json_encode(['status' => 'success', 'message' => 'File deleted']);
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Failed to delete file']);
|
||||
}
|
||||
|
||||
}
|
||||
120
pub/api/v1/devices/index.php
Normal file
120
pub/api/v1/devices/index.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_devices;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_devices.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/imageProcessor.php';
|
||||
|
||||
$API_devices = new API_devices();
|
||||
|
||||
if ($API_devices->request_method === 'GET') {
|
||||
|
||||
# GET the devices
|
||||
|
||||
$API_devices->checkPermissions('admin-devices', 'RO');
|
||||
|
||||
} elseif ($API_devices->request_method === 'POST') {
|
||||
|
||||
# create an new device
|
||||
|
||||
$API_devices->checkPermissions('admin-devices', 'RW');
|
||||
|
||||
$ImageData = $API_devices->createDeviceImage(['min_width' => 500, 'max_width' => 1000, 'min_height' => 500, 'max_height' => 1000, 'square' => true, 'allowed_types' => ['image/png'], 'max_size_kb' => 1024, 'transparent' => true]);
|
||||
$ImageDataThumbnail = $API_devices->createDeviceImage(['min_width' => 64, 'max_width' => 64, 'min_height' => 64, 'max_height' => 64, 'square' => true, 'allowed_types' => ['image/png'], 'max_size_kb' => 1024, 'transparent' => true]);
|
||||
$API_devices->postedData['device_eol'] = $_POST['device_eol'] !== ''
|
||||
? DateTime::createFromFormat('d/m/Y', $_POST['device_eol'])?->getTimestamp()
|
||||
: null;
|
||||
$API_devices->postedData['device_extensions'] = isset($_POST['device_extensions']) ? json_encode($_POST['device_extensions']) : '[""]';
|
||||
$API_devices->postedData['device_extra'] = preg_replace('/\s+/', '', str_replace(["\r", "\n"], '', $_POST['device_extra'] ?? '{}'));
|
||||
|
||||
if ($ImageData) {
|
||||
$API_devices->postedData['device_image'] = $ImageData;
|
||||
}
|
||||
if ($ImageDataThumbnail) {
|
||||
$API_devices->postedData['device_image_thumbnail'] = $ImageDataThumbnail;
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
'device_vendor_uuid' => ['type' => 'uuid'],
|
||||
'device_type' => ['type' => 'enum', 'values' => ['base', 'handset', 'module', 'phone']],
|
||||
'device_name' => ['type' => 'string'],
|
||||
'device_slugify' => ['type' => 'slugify'],
|
||||
'device_enabled' => ['type' => 'boolean'],
|
||||
'device_notes' => ['type' => 'string'],
|
||||
'device_eol' => ['type' => 'timestamp'],
|
||||
'device_extensions' => ['type' => 'json'],
|
||||
'device_extra' => ['type' => 'string'],
|
||||
];
|
||||
|
||||
$optionalFields = [
|
||||
'device_image' => ['type' => 'base64'],
|
||||
'device_image_thumbnail' => ['type' => 'base64']
|
||||
];
|
||||
|
||||
$API_devices->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$API_devices->createDevice();
|
||||
|
||||
} elseif ($API_devices->request_method === 'PUT') {
|
||||
|
||||
# Edit the device
|
||||
$API_devices->checkPermissions('admin-devices', 'RW');
|
||||
|
||||
# process the posted image (if any)
|
||||
$ImageData = $API_devices->createDeviceImage(['min_width' => 500, 'max_width' => 1000, 'min_height' => 500, 'max_height' => 1000, 'square' => true, 'allowed_types' => ['image/png'], 'max_size_kb' => 1024, 'transparent' => true]);
|
||||
$ImageDataThumbnail = $API_devices->createDeviceImage(['min_width' => 64, 'max_width' => 64, 'min_height' => 64, 'max_height' => 64, 'square' => true, 'allowed_types' => ['image/png'], 'max_size_kb' => 1024, 'transparent' => true]);
|
||||
$API_devices->postedData['device_eol'] = $_POST['device_eol'] !== ''
|
||||
? DateTime::createFromFormat('d/m/Y', $_POST['device_eol'])?->getTimestamp()
|
||||
: null;
|
||||
$API_devices->postedData['device_extensions'] = isset($_POST['device_extensions']) ? json_encode($_POST['device_extensions']) : '[""]';
|
||||
$API_devices->postedData['device_extra'] = preg_replace('/\s+/', '', str_replace(["\r", "\n"], '', $_POST['device_extra'] ?? '{}'));
|
||||
|
||||
if ($ImageData) {
|
||||
$API_devices->postedData['device_image'] = $ImageData;
|
||||
}
|
||||
if ($ImageDataThumbnail) {
|
||||
$API_devices->postedData['device_image_thumbnail'] = $ImageDataThumbnail;
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
'device_uuid' => ['type' => 'uuid'],
|
||||
'device_vendor_uuid' => ['type' => 'uuid'],
|
||||
'device_name' => ['type' => 'string'],
|
||||
'device_enabled' => ['type' => 'boolean'],
|
||||
'device_notes' => ['type' => 'string'],
|
||||
'device_eol' => ['type' => 'timestamp'],
|
||||
'device_extensions' => ['type' => 'json'],
|
||||
'device_extra' => ['type' => 'string'],
|
||||
];
|
||||
|
||||
$optionalFields = [
|
||||
'device_image' => ['type' => 'base64'],
|
||||
'device_image_thumbnail' => ['type' => 'base64']
|
||||
];
|
||||
|
||||
$API_devices->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'device_uuid', 1 => $API_devices->data['device_uuid']]]];
|
||||
$API_devices->getDevices();
|
||||
|
||||
$API_devices->updateDevice();
|
||||
|
||||
} elseif ($API_devices->request_method === 'DELETE') {
|
||||
|
||||
# delete an device
|
||||
|
||||
$API_devices->checkPermissions('admin-devices', 'RW');
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_devices->return_url = false;
|
||||
|
||||
$requiredFields = ['device_uuid' => ['type' => 'uuid']];
|
||||
$API_devices->validateData($requiredFields);
|
||||
|
||||
# check if the device exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'device_uuid', 1 => $API_devices->data['device_uuid']]]];
|
||||
|
||||
# Delete the device from the database.
|
||||
$API_devices->deleteDevice();
|
||||
}
|
||||
43
pub/api/v1/mailsettings/index.php
Normal file
43
pub/api/v1/mailsettings/index.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_mailsettings;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_mailsettings.php';
|
||||
|
||||
$API_mailsettings = new API_mailsettings();
|
||||
|
||||
if ($API_mailsettings->request_method === 'PUT') {
|
||||
# Edit the mailsettings of the platform
|
||||
|
||||
$API_mailsettings->checkPermissions('admin-mailsettings', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'portal_uuid' => ['type' => 'uuid'],
|
||||
'mail_from_name' => ['type' => 'string'],
|
||||
'mail_from_address' => ['type' => 'email'],
|
||||
'mail_smtp_host' => ['type' => 'string'],
|
||||
'mail_smtp_secure' => ['type' => 'enum', 'values' => ['tls', 'ssl', 'no']],
|
||||
'mail_smtp_port' => ['type' => 'int', 'min' => 4, 'max' => 65535],
|
||||
'mail_smtp_auth' => ['type' => 'boolean'],
|
||||
'mail_smtp_user' => ['type' => 'email'],
|
||||
'mail_smtp_pass' => ['type' => 'string']
|
||||
];
|
||||
# check if the password is changed
|
||||
$updatePassword = str_contains($API_mailsettings->postedData['mail_smtp_pass'], '******') ? false : true;
|
||||
if ($updatePassword) {
|
||||
if (strlen($API_mailsettings->postedData['mail_smtp_pass']) < 12) {
|
||||
$API_mailsettings->apiOutput(400, ['error' => 'Password too short']);
|
||||
}
|
||||
|
||||
if (preg_match('/^(.)\1{5,}$/', $API_mailsettings->postedData['mail_smtp_pass'])) {
|
||||
$API_mailsettings->apiOutput(400, ['error' => 'Password insecure']);
|
||||
}
|
||||
}
|
||||
|
||||
$API_mailsettings->validateData($requiredFields);
|
||||
|
||||
# Update the permission
|
||||
$API_mailsettings->updateMailSettings($updatePassword);
|
||||
|
||||
}
|
||||
38
pub/api/v1/office/stompjes/index.php
Normal file
38
pub/api/v1/office/stompjes/index.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_office_stompjes;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_office_stompjes.php';
|
||||
|
||||
$API_office_stompjes = new API_office_stompjes();
|
||||
|
||||
|
||||
if ($API_office_stompjes->request_method === 'POST') {
|
||||
$API_office_stompjes->checkPermissions('ofice-stompjes-canstomp', 'RW');
|
||||
|
||||
$API_office_stompjes->return_url = false;
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid']
|
||||
];
|
||||
|
||||
$API_office_stompjes->validateData($requiredFields);
|
||||
|
||||
$modules = $API_office_stompjes->addStomp();
|
||||
|
||||
$API_office_stompjes->apiOutput($code = 200, ['success' => 'stomp added successfully.']);
|
||||
} elseif ($API_office_stompjes->request_method === 'DELETE') {
|
||||
|
||||
# Only superuser can delete permission due to fact that the backend needs programming when setting a permission
|
||||
$API_office_stompjes->checkPermissions('ofice-stompjes', 'RW');
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_office_stompjes->return_url = false;
|
||||
|
||||
$requiredFields = ['stomp_uuid' => ['type' => 'uuid']];
|
||||
$API_office_stompjes->validateData($requiredFields);
|
||||
|
||||
# delete permission
|
||||
$API_office_stompjes->deleteStomp();
|
||||
}
|
||||
87
pub/api/v1/permissions/index.php
Normal file
87
pub/api/v1/permissions/index.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_permissions;
|
||||
|
||||
session_start();
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_permissions.php';
|
||||
|
||||
$API_permissions = new API_permissions();
|
||||
|
||||
if ($API_permissions->request_method === 'GET') {
|
||||
|
||||
# Retrieve all the permissions a user and return them.
|
||||
$API_permissions->checkPermissions('admin-access-control-permissions', 'RO');
|
||||
|
||||
$requiredFields = [];
|
||||
$optionalFields = [
|
||||
'permission_uuid' => ['type' => 'uuid'],
|
||||
'permission_name' => ['type' => 'string'],
|
||||
'permission_slugify' => ['type' => 'slugify'],
|
||||
'permission_description' => ['type' => 'string'],
|
||||
'permission_create_timestamp' => ['type' => 'timestamp'],
|
||||
'permission_modified_timestamp' => ['type' => 'timestamp']
|
||||
];
|
||||
$API_permissions->validateData($requiredFields, $optionalFields);
|
||||
$permissions = $API_permissions->getPermission();
|
||||
|
||||
$API_permissions->apiOutput($code = 200, ['success' => $permissions], 'permission_created');
|
||||
|
||||
} elseif ($API_permissions->request_method === 'POST') {
|
||||
|
||||
# Only superuser can create permission due to fact that the backend needs programming when setting a permission
|
||||
|
||||
if (!$API_permissions->isSuperuser()) {
|
||||
$API_permissions->apiOutput(401, ['error' => 'You are not authorized to access this resource.']);
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
'permission_name' => ['type' => 'string', 'min' => 6, 'max' => 255],
|
||||
'permission_slugify' => ['type' => 'slugify', 'min' => 6, 'max' => 255],
|
||||
'permission_description' => ['type' => 'string', 'min' => 1, 'max' => 512],
|
||||
'module_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
|
||||
$API_permissions->validateData($requiredFields);
|
||||
$API_permissions->createPermission();
|
||||
|
||||
} elseif ($API_permissions->request_method === 'PUT') {
|
||||
|
||||
# Update the permission name and description
|
||||
$API_permissions->checkPermissions('admin-access-control-permissions', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'permission_uuid' => ['type' => 'uuid'],
|
||||
'permission_name' => ['type' => 'string', 'min' => 6, 'max' => 255],
|
||||
'permission_description' => ['type' => 'string', 'min' => 1, 'max' => 512],
|
||||
'module_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
$API_permissions->validateData($requiredFields);
|
||||
|
||||
# check if the permission exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'permission_uuid', 1 => $API_permissions->data['permission_uuid']]]];
|
||||
$API_permissions->getPermission();
|
||||
|
||||
# Update the permission
|
||||
$API_permissions->updatePermission();
|
||||
|
||||
} elseif ($API_permissions->request_method === 'DELETE') {
|
||||
|
||||
# Only superuser can delete permission due to fact that the backend needs programming when setting a permission
|
||||
if (!$API_permissions->isSuperuser()) {
|
||||
$API_permissions->apiOutput(401, ['error' => 'You are not authorized to access this resource.']);
|
||||
}
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_permissions->return_url = false;
|
||||
|
||||
$requiredFields = ['permission_uuid' => ['type' => 'uuid']];
|
||||
$API_permissions->validateData($requiredFields);
|
||||
|
||||
# check if the permission exists
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'permission_uuid', 1 => $API_permissions->data['permission_uuid']]]];
|
||||
$API_permissions->getPermission();
|
||||
|
||||
# delete permission
|
||||
$API_permissions->deletePermission();
|
||||
}
|
||||
94
pub/api/v1/platforms/index.php
Normal file
94
pub/api/v1/platforms/index.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_platforms;
|
||||
use api\classes\imageProcessor;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_platforms.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/imageProcessor.php';
|
||||
|
||||
$API_platforms = new API_platforms();
|
||||
|
||||
if ($API_platforms->request_method === 'GET') {
|
||||
# get all the platforms
|
||||
$API_platforms->checkPermissions('admin-platforms', 'RO');
|
||||
|
||||
} elseif ($API_platforms->request_method === 'POST') {
|
||||
# create a new platform
|
||||
|
||||
$API_platforms->checkPermissions('admin-platforms', 'RW');
|
||||
|
||||
try {
|
||||
$imageProcessor = new imageProcessor('platform_image');
|
||||
$imageProcessor->imageRestrictions = [
|
||||
'min_width' => 200,
|
||||
'max_width' => 200,
|
||||
'min_height' => 200,
|
||||
'max_height' => 200,
|
||||
'square' => true,
|
||||
'allowed_types' => ['image/png'],
|
||||
'max_size_kb' => 1024
|
||||
];
|
||||
|
||||
$imageProcessor->validateAndProcess();
|
||||
$finalImageData = $imageProcessor->returnBase64image();
|
||||
} catch (Exception $e) {
|
||||
$API_platforms->apiOutput(401, ['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
$API_platforms->postedData['platform_image'] = $finalImageData;
|
||||
|
||||
$requiredFields = [
|
||||
'platform_name' => ['type' => 'string'],
|
||||
'platform_slugify' => ['type' => 'slugify'],
|
||||
'platform_enabled' => ['type' => 'boolean'],
|
||||
'platform_description' => ['type' => 'string'],
|
||||
];
|
||||
$optionalFields = ['platform_image' => ['type' => 'string']];
|
||||
|
||||
$API_platforms->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$API_platforms->createPlatforms();
|
||||
} elseif ($API_platforms->request_method === 'PUT') {
|
||||
|
||||
# edit a platform
|
||||
$API_platforms->checkPermissions('admin-platforms', 'RW');
|
||||
|
||||
try {
|
||||
$imageProcessor = new imageProcessor('platform_image');
|
||||
$imageProcessor->imageRestrictions = [
|
||||
'min_width' => 200,
|
||||
'max_width' => 200,
|
||||
'min_height' => 200,
|
||||
'max_height' => 200,
|
||||
'square' => true,
|
||||
'allowed_types' => ['image/png'],
|
||||
'max_size_kb' => 1024
|
||||
];
|
||||
$imageProcessor->validateAndProcess();
|
||||
$finalImageData = $imageProcessor->returnBase64image();
|
||||
} catch (Exception $e) {
|
||||
$API_platforms->apiOutput(401, ['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
if ($finalImageData) {
|
||||
$API_platforms->postedData['platform_image'] = $finalImageData;
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
'platform_uuid' => ['type' => 'uuid'],
|
||||
'platform_name' => ['type' => 'string'],
|
||||
'platform_enabled' => ['type' => 'boolean'],
|
||||
'platform_description' => ['type' => 'string'],
|
||||
];
|
||||
$optionalFields = ['platform_image' => ['type' => 'string']];
|
||||
|
||||
|
||||
$API_platforms->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'platform_uuid', 1 => $API_platforms->data['platform_uuid']]]];
|
||||
$API_platforms->getPlatforms();
|
||||
|
||||
$API_platforms->editPlatforms();
|
||||
|
||||
}
|
||||
28
pub/api/v1/portalsettings/index.php
Normal file
28
pub/api/v1/portalsettings/index.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_portalsettings;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_portalsettings.php';
|
||||
|
||||
$API_portalsettings = new API_portalsettings();
|
||||
|
||||
if ($API_portalsettings->request_method === 'PUT') {
|
||||
|
||||
# Edit the portal settings of the platform
|
||||
|
||||
$API_portalsettings->checkPermissions('admin-portalsettings', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'portal_uuid' => ['type' => 'uuid'],
|
||||
'portal_name' => ['type' => 'string'],
|
||||
'portal_provider_name' => ['type' => 'string'],
|
||||
'admin_auth_methods' => ['type' => 'string']
|
||||
];
|
||||
|
||||
$API_portalsettings->validateData($requiredFields);
|
||||
|
||||
# Update the permission
|
||||
$API_portalsettings->updatePortalSettings();
|
||||
|
||||
}
|
||||
52
pub/api/v1/servers/index.php
Normal file
52
pub/api/v1/servers/index.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_servers;
|
||||
|
||||
session_start();
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_servers.php';
|
||||
|
||||
$API_servers = new API_servers();
|
||||
|
||||
if ($API_servers->request_method === 'POST') {
|
||||
$API_servers->checkPermissions('servers', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'server_vm_id' => ['type' => 'string'],
|
||||
];
|
||||
|
||||
$optionalFields = [
|
||||
'server_vm_host_id' => ['type' => 'string'],
|
||||
'server_vm_host_name' => ['type' => 'string'],
|
||||
'company_uuid' => ['type' => 'string'],
|
||||
'server_power_state' => ['type' => 'enum', 'values' => ['Running', 'Off']],
|
||||
'server_state' => ['type' => 'enum', 'values' => ['new', 'active', 'deleted', 'trial', 'disabled']],
|
||||
'server_hostname' => ['type' => 'string'],
|
||||
'server_os' => ['type' => 'string'],
|
||||
'server_cpu' => ['type' => 'int'],
|
||||
'server_memory' => ['type' => 'int'],
|
||||
'server_memory_demand' => ['type' => 'int'],
|
||||
'server_disks' => ['type' => 'json'],
|
||||
'server_ipv4' => ['type' => 'json'],
|
||||
'server_ipv6' => ['type' => 'json'],
|
||||
'server_vm_generation' => ['type' => 'int'],
|
||||
'server_vm_snapshot' => ['type' => 'int'],
|
||||
'server_licenses' => ['type' => 'json'],
|
||||
'server_backup' => ['type' => 'json'],
|
||||
'server_description' => ['type' => 'string'],
|
||||
];
|
||||
|
||||
if (isset($API_servers->postedData['servers'])) {
|
||||
// multiple servers are posted
|
||||
$allServers = $API_servers->postedData['servers'];
|
||||
|
||||
foreach ($allServers as $server) {
|
||||
$API_servers->processServerData($server, $requiredFields, $optionalFields);
|
||||
}
|
||||
} else {
|
||||
// Single server update
|
||||
$API_servers->processServerData($API_servers->postedData, $requiredFields, $optionalFields);
|
||||
}
|
||||
|
||||
$API_servers->apiOutput(200, ['success' => "Server(s) modified or updated successfully."]);
|
||||
}
|
||||
26
pub/api/v1/sources/inserve/index.php
Normal file
26
pub/api/v1/sources/inserve/index.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_inserve;
|
||||
|
||||
session_start();
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_inserve.php';
|
||||
|
||||
$API_inserve = new API_inserve();
|
||||
$API_inserve->setupConnection();
|
||||
|
||||
|
||||
if ($API_inserve->request_method === 'GET') {
|
||||
|
||||
if ($_GET['action'] = 'auth/me') {
|
||||
|
||||
# This api call, when called from the frontend will not be forwarding to a url.
|
||||
$API_inserve->return_url = false;
|
||||
$auth = $API_inserve->authMe();
|
||||
|
||||
http_response_code($API_inserve->httpCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
32
pub/api/v1/sources/inserve/subscriptions/index.php
Normal file
32
pub/api/v1/sources/inserve/subscriptions/index.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_inserve;
|
||||
|
||||
session_start();
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_inserve.php';
|
||||
|
||||
|
||||
$API_inserve = new API_inserve();
|
||||
|
||||
if ($API_inserve->request_method === 'GET') {
|
||||
|
||||
if ($_GET['action'] == 'sync-companies') {
|
||||
# This syncs the company id's from Sentri to the Inserve cloudDistributor
|
||||
# These are the same id's but it Inserve requires it to be synced to the cloudDistributor
|
||||
$API_inserve->checkPermissions('servers', 'RW');
|
||||
$API_inserve->setupConnection();
|
||||
|
||||
$API_inserve->syncCompaniesFromSentri();
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($_GET['action'] == 'sync-subscriptions') {
|
||||
$API_inserve->checkPermissions('servers', 'RW');
|
||||
$API_inserve->setupConnection();
|
||||
|
||||
$API_inserve->syncServerLicencesToInserve();
|
||||
|
||||
}
|
||||
}
|
||||
37
pub/api/v1/system/modules/index.php
Normal file
37
pub/api/v1/system/modules/index.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_system_modules;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_system_modules.php';
|
||||
|
||||
$API_system_modules = new API_system_modules();
|
||||
|
||||
if ($API_system_modules->request_method === 'GET') {
|
||||
# this part here is not tested (the whole GET part)
|
||||
$API_system_modules->checkPermissions('admin-modules', 'RO');
|
||||
|
||||
$requiredFields = [];
|
||||
$API_system_modules->validateData($requiredFields);
|
||||
|
||||
$modules = $API_system_modules->getModules();
|
||||
|
||||
$API_system_modules->apiOutput($code = 200, ['success' => $modules], '');
|
||||
|
||||
} elseif ($API_system_modules->request_method === 'PUT') {
|
||||
# Enable or disable a module
|
||||
$API_system_modules->checkPermissions('admin-modules', 'RW');
|
||||
|
||||
# This api call, when called from the frontend will not be forwarding to a url.
|
||||
$API_system_modules->return_url = false;
|
||||
|
||||
$requiredFields = [
|
||||
'module_uuid' => ['type' => 'uuid'],
|
||||
'module_enabled' => ['type' => 'boolean'],
|
||||
];
|
||||
$API_system_modules->validateData($requiredFields);
|
||||
|
||||
$API_system_modules->enableModule();
|
||||
|
||||
}
|
||||
|
||||
30
pub/api/v1/system/sources/inserve/index.php
Normal file
30
pub/api/v1/system/sources/inserve/index.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_system_sources;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_system_sources.php';
|
||||
|
||||
$API_system_sources = new API_system_sources();
|
||||
|
||||
if ($API_system_sources->request_method === 'POST') {
|
||||
# Enable or disable a module
|
||||
$API_system_sources->checkPermissions('admin-sources', 'RW');
|
||||
|
||||
if ($_POST['source_name'] == 'inserve') {
|
||||
$requiredFields = [
|
||||
'source_name' => ['type' => 'string'],
|
||||
'source_url' => ['type' => 'string'],
|
||||
'source_auth_token' => ['type' => 'string'],
|
||||
];
|
||||
} else {
|
||||
$API_system_sources->apiOutput(400, ['error' => 'Error: no valid source_name posted']);
|
||||
}
|
||||
|
||||
$API_system_sources->validateData($requiredFields);
|
||||
|
||||
if ($_POST['source_name'] == 'inserve') {
|
||||
$API_system_sources->inserveUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
67
pub/api/v1/user-groups/index.php
Normal file
67
pub/api/v1/user-groups/index.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_usergroups;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_usergroups.php';
|
||||
|
||||
|
||||
$API_usergroups = new API_usergroups();
|
||||
|
||||
if ($API_usergroups->request_method === 'GET') {
|
||||
|
||||
# GET a user group(s)
|
||||
|
||||
} elseif ($API_usergroups->request_method === 'POST') {
|
||||
|
||||
# Create a new user group
|
||||
|
||||
$API_usergroups->checkPermissions('admin-access-control-user-groups', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'user_group_name' => ['type' => 'string'],
|
||||
'user_group_slugify' => ['type' => 'slugify'],
|
||||
'user_group_weight' => ['type' => 'int'],
|
||||
'user_group_type' => ['type' => 'enum', 'values' => ['admin', 'user']],
|
||||
];
|
||||
|
||||
$API_usergroups->validateData($requiredFields);
|
||||
|
||||
# superuser group is a fixed group name for the superuser
|
||||
if ($API_usergroups->data['user_group_name'] === 'superuser' || $API_usergroups->data['user_group_slugify'] === 'superuser') {
|
||||
$API_usergroups->apiOutput(400, ['error' => 'superuser group cannot be created'], 'cannot_add_superuser_group');
|
||||
}
|
||||
|
||||
$API_usergroups->createUsergroups();
|
||||
|
||||
|
||||
} elseif ($API_usergroups->request_method === 'PUT') {
|
||||
|
||||
# Update a user group
|
||||
|
||||
$requiredFields = [
|
||||
'user_group_uuid' => ['type' => 'uuid'],
|
||||
'user_group_name' => ['type' => 'string'],
|
||||
'user_group_weight' => ['type' => 'int'],
|
||||
];
|
||||
|
||||
$API_usergroups->validateData($requiredFields);
|
||||
|
||||
$API_usergroups->updateUserGroup();
|
||||
|
||||
} elseif ($API_usergroups->request_method === 'DELETE') {
|
||||
|
||||
# Delete a user group
|
||||
|
||||
$API_usergroups->checkPermissions('admin-access-control-user-groups', 'RW');
|
||||
|
||||
# when called from the frontend will not be forwarding to a url since when its called from the frontend it doesnt need a redirection
|
||||
$API_usergroups->return_url = false;
|
||||
|
||||
$requiredFields = ['user_group_uuid' => ['type' => 'uuid']];
|
||||
|
||||
$API_usergroups->validateData($requiredFields);
|
||||
|
||||
# Delete the device from the database.
|
||||
$API_usergroups->deleteUsergroup();
|
||||
}
|
||||
116
pub/api/v1/users/apitoken/index.php
Normal file
116
pub/api/v1/users/apitoken/index.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_apitoken;
|
||||
use api\classes\API_users;
|
||||
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_apitoken.php';
|
||||
|
||||
$API_apitoken = new API_apitoken();
|
||||
|
||||
if ($API_apitoken->request_method === 'GET') {
|
||||
|
||||
# Retrieve all the API tokens from a user and return them.
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
|
||||
$API_apitoken->validateData($requiredFields);
|
||||
|
||||
if ($API_apitoken->getUserUuid() === $API_apitoken->data['user_uuid']) {
|
||||
$API_apitoken->checkPermissions('user-apitoken-self', 'RW');
|
||||
|
||||
} else {
|
||||
|
||||
$API_apitoken->checkPermissions('user-apitoken-others', 'RO');
|
||||
|
||||
}
|
||||
|
||||
$apitokens = $API_apitoken->getTokens();
|
||||
|
||||
$API_apitoken->apiOutput($code = 200, ['success' => $apitokens], 'api_token_created');
|
||||
|
||||
} elseif ($API_apitoken->request_method === 'POST') {
|
||||
|
||||
# Creates a new API Token. First check if the uuid is correct and then check the permission
|
||||
# After that create a new token, retrieve the newly created api_token and give a response.
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
$API_apitoken->validateData($requiredFields);
|
||||
|
||||
# First retrieve the user_uuid from the post and lookup the user
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_users.php';
|
||||
|
||||
$API_users = new API_users();
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $API_apitoken->data['user_uuid']]]];
|
||||
$user_data = $API_users->getUser()[0];
|
||||
|
||||
$API_apitoken->validateData($requiredFields);
|
||||
|
||||
if ($API_apitoken->getUserUuid() === $API_apitoken->data['user_uuid']) {
|
||||
$API_apitoken->checkPermissions('user-apitoken-self', 'RW');
|
||||
|
||||
} else {
|
||||
if ($user_data['user_email'] === 'superuser') {
|
||||
$API_apitoken->apiOutput(401, ['error' => 'You are not authorized to access this resource.']);
|
||||
}
|
||||
$API_apitoken->checkPermissions('user-apitoken-others', 'RW');
|
||||
}
|
||||
|
||||
$API_apitoken->createNewToken();
|
||||
|
||||
} elseif ($API_apitoken->request_method === 'PUT') {
|
||||
|
||||
# Change the revoked status of an API token
|
||||
|
||||
# This api call, when called from the frontend will not be forwarding to a url.
|
||||
$API_apitoken->return_url = false;
|
||||
|
||||
$requiredFields = [
|
||||
'api_token_uuid' => ['type' => 'uuid'],
|
||||
'api_token_revoked' => ['type' => 'boolean'],
|
||||
];
|
||||
$API_apitoken->validateData($requiredFields);
|
||||
$api_token_data = $API_apitoken->getToken();
|
||||
|
||||
if ($API_apitoken->getUserUuid() === $api_token_data['user_uuid']) {
|
||||
$API_apitoken->checkPermissions('user-apitoken-self', 'RW');
|
||||
} else {
|
||||
if ($api_token_data['user_email'] === 'superuser') {
|
||||
$API_apitoken->apiOutput(401, ['error' => 'You are not authorized to access this resource.']);
|
||||
}
|
||||
$API_apitoken->checkPermissions('user-apitoken-others', 'RW');
|
||||
}
|
||||
|
||||
|
||||
$API_apitoken->revokeToken();
|
||||
|
||||
} elseif ($API_apitoken->request_method === 'DELETE') {
|
||||
|
||||
# Deletes an API token, requies DELETE with 'api_token_uuid' first retrieve the uuid of the user with getToken then check
|
||||
# if the user is another user or itself
|
||||
|
||||
# This api call, when called from the frontend will not be forwarding to a url.
|
||||
$API_apitoken->return_url = false;
|
||||
|
||||
$requiredFields = [
|
||||
'api_token_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
$API_apitoken->validateData($requiredFields);
|
||||
$api_token_data = $API_apitoken->getToken();
|
||||
|
||||
if ($API_apitoken->getUserUuid() === $api_token_data['user_uuid']) {
|
||||
$API_apitoken->checkPermissions('user-apitoken-self', 'RW');
|
||||
} else {
|
||||
if ($api_token_data['user_email'] === 'superuser') {
|
||||
$API_apitoken->apiOutput(401, ['error' => 'You are not authorized to access this resource.']);
|
||||
}
|
||||
$API_apitoken->checkPermissions('user-apitoken-others', 'RW');
|
||||
}
|
||||
|
||||
$API_apitoken->deleteToken();
|
||||
|
||||
}
|
||||
41
pub/api/v1/users/avatar/index.php
Normal file
41
pub/api/v1/users/avatar/index.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
|
||||
use api\classes\API_usersavatar;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_usersavatar.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/imageProcessor.php';
|
||||
|
||||
$API_usersavatar = new API_usersavatar();
|
||||
|
||||
if ($API_usersavatar->request_method === 'GET') {
|
||||
|
||||
} elseif ($API_usersavatar->request_method === 'POST') {
|
||||
# Reset a users password and send a email to the user to set a new password
|
||||
|
||||
$API_usersavatar->postedData['user_profile_picture'] = $API_usersavatar->createUserImage(['min_width' => 500, 'max_width' => 1000, 'min_height' => 500, 'max_height' => 1000, 'square' => true, 'allowed_types' => ['image/png'], 'max_size_kb' => 1024, 'transparent' => true]);
|
||||
$API_usersavatar->postedData['user_profile_picture_thumbnail'] = $API_usersavatar->createUserImage(['min_width' => 64, 'max_width' => 64, 'min_height' => 64, 'max_height' => 64, 'square' => true, 'allowed_types' => ['image/png'], 'max_size_kb' => 1024, 'transparent' => true]);
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
'user_profile_picture' => ['type' => 'base64'],
|
||||
'user_profile_picture_thumbnail' => ['type' => 'base64'],
|
||||
];
|
||||
|
||||
$API_usersavatar->validateData($requiredFields);
|
||||
|
||||
# if the user is different from the user logged in, check the required permissions
|
||||
if ($API_usersavatar->data['user_uuid'] != $API_usersavatar->getUserUuid()) {
|
||||
$API_usersavatar->checkPermissions('admin-access-admins', 'RW');
|
||||
}
|
||||
|
||||
$API_usersavatar->updateUserImage();
|
||||
|
||||
$API_usersavatar->apiOutput(200, ['success' => 'Avatar was successfully changed.']);
|
||||
|
||||
} elseif ($API_usersavatar->request_method === 'PUT') {
|
||||
|
||||
} elseif ($API_usersavatar->request_method === 'DELETE') {
|
||||
|
||||
}
|
||||
89
pub/api/v1/users/index.php
Normal file
89
pub/api/v1/users/index.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_users;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_users.php';
|
||||
|
||||
$API_users = new API_users();
|
||||
|
||||
if ($API_users->request_method === 'GET') {
|
||||
#echo json_encode($api->getAllUsers());
|
||||
|
||||
|
||||
} elseif ($API_users->request_method === 'POST') {
|
||||
# create a new user
|
||||
$API_users->checkPermissions('admin-access-admins', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'user_group_uuid' => ['type' => 'uuid'],
|
||||
'user_email' => ['type' => 'email'],
|
||||
'user_first_name' => ['type' => 'string'],
|
||||
'user_last_name' => ['type' => 'string'],
|
||||
'user_full_name' => ['type' => 'string'],
|
||||
'user_phone_number' => ['type' => 'string'],
|
||||
'user_status' => ['type' => 'enum', 'values' => ['active', 'inactive', 'banned', 'pending']],
|
||||
'user_password' => ['type' => 'string'],
|
||||
'user_pref_language' => ['type' => 'string'],
|
||||
'user_password_reset_token' => ['type' => 'string'],
|
||||
'user_password_reset_expires' => ['type' => 'int'],
|
||||
];
|
||||
|
||||
# The user will need to verify their email, the password field cannot be NULL so set an random password for now till the user resets it on when verifing there email
|
||||
$random_string = substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01', 64)), 0, rand(50, 64));
|
||||
$user_password = password_hash($random_string, PASSWORD_BCRYPT, ["cost" => 12]);
|
||||
$API_users->postedData['user_password'] = $user_password;
|
||||
|
||||
$API_users->postedData['user_full_name'] = trim($_POST['user_first_name'] . ' ' . $_POST['user_last_name']);
|
||||
$API_users->postedData['user_pref_language'] = $_POST['user_pref_language'] ?? 'en';
|
||||
|
||||
# Password reset token that will be send to the newly created user
|
||||
$API_users->postedData['user_password_reset_token'] = bin2hex(random_bytes(32));
|
||||
$API_users->postedData['user_password_reset_expires'] = time() + 86400;
|
||||
|
||||
$API_users->validateData($requiredFields);
|
||||
$API_users->createUser();
|
||||
|
||||
} elseif ($API_users->request_method === 'PUT') {
|
||||
|
||||
# Edit a user
|
||||
$API_users->checkPermissions('admin-access-admins', 'RW');
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
'user_group_uuid' => ['type' => 'uuid'],
|
||||
'user_email' => ['type' => 'email'],
|
||||
'user_first_name' => ['type' => 'string'],
|
||||
'user_last_name' => ['type' => 'string'],
|
||||
'user_full_name' => ['type' => 'string'],
|
||||
'user_phone_number' => ['type' => 'string'],
|
||||
'user_status' => ['type' => 'enum', 'values' => ['active', 'inactive', 'banned', 'pending']],
|
||||
'user_pref_language' => ['type' => 'string'],
|
||||
'user_stompable' => ['type' => 'boolean']
|
||||
];
|
||||
|
||||
$API_users->postedData['user_full_name'] = trim($_POST['user_first_name'] . ' ' . $_POST['user_last_name']);
|
||||
$API_users->postedData['user_pref_language'] = $_POST['user_pref_language'] ?? 'en';
|
||||
$API_users->postedData['user_stompable'] = (bool)$_POST['user_stompable'];
|
||||
|
||||
|
||||
$API_users->validateData($requiredFields);
|
||||
|
||||
|
||||
$API_users->updateUser();
|
||||
|
||||
} elseif ($API_users->request_method === 'DELETE') {
|
||||
|
||||
|
||||
$API_users->return_url = false;
|
||||
|
||||
$API_users->checkPermissions('admin-access-admins', 'RW');
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
|
||||
|
||||
$API_users->validateData($requiredFields);
|
||||
|
||||
$API_users->deleteUser();
|
||||
}
|
||||
68
pub/api/v1/users/mfa/index.php
Normal file
68
pub/api/v1/users/mfa/index.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_mfa.php';
|
||||
require $_SERVER['DOCUMENT_ROOT'] . '/../vendor/autoload.php';
|
||||
include_once $_SERVER['DOCUMENT_ROOT'] . '/login/php/authFunctions.php';
|
||||
|
||||
|
||||
use api\classes\API_mfa;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
use RobThree\Auth\Providers\Qr\EndroidQrCodeWithLogoProvider;
|
||||
|
||||
$API_mfa = new API_mfa();
|
||||
|
||||
if ($API_mfa->request_method === 'GET') {
|
||||
|
||||
} elseif ($API_mfa->request_method === 'POST') {
|
||||
# Setup a new MFA secret its posted from mfaSetup.php where it generated a secret
|
||||
|
||||
if (checkLoginAttempts() > 10) {
|
||||
echo 'too many attempts, please try again later.';
|
||||
exit;
|
||||
}
|
||||
|
||||
# check if the secret is in the session created at the mfaSetup.php file
|
||||
if (!isset($_SESSION['mfasetup']['secret'])) {
|
||||
$this->apiOutput(400, ['error' => 'secret not found.']);
|
||||
}
|
||||
|
||||
$tfa = new TwoFactorAuth(new EndroidQrCodeWithLogoProvider());
|
||||
|
||||
$API_mfa->postedData['user_uuid'] = $_SESSION['user']['user_uuid'];
|
||||
$API_mfa->postedData['user_two_factor_secret'] = $_SESSION['mfasetup']['secret'];
|
||||
$API_mfa->postedData['verificationCode'] = linkVerificationPosts(); # The code is entered in six loose posts this wil link it togheter
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
'user_two_factor_secret' => ['type' => 'string'],
|
||||
'verificationCode' => ['type' => 'string', 'min' => 6, 'max' => 6],
|
||||
];
|
||||
|
||||
$API_mfa->validateData($requiredFields);
|
||||
|
||||
|
||||
$result = $tfa->verifyCode($API_mfa->postedData['user_two_factor_secret'], $API_mfa->postedData['verificationCode']);
|
||||
if (!$result) {
|
||||
addLoginAttempts();
|
||||
$API_mfa->apiOutput(401, ['error' => 'Invalid verification code.']);
|
||||
}
|
||||
|
||||
$API_mfa->enableMFA();
|
||||
|
||||
} elseif ($API_mfa->request_method === 'PUT') {
|
||||
|
||||
} elseif ($API_mfa->request_method === 'DELETE') {
|
||||
|
||||
# Delete a mfa code for a user
|
||||
|
||||
$API_mfa->return_url = false;
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
];
|
||||
|
||||
$API_mfa->validateData($requiredFields);
|
||||
|
||||
$API_mfa->disableMFA();
|
||||
|
||||
}
|
||||
78
pub/api/v1/users/resetpassword/index.php
Normal file
78
pub/api/v1/users/resetpassword/index.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_resetpassword;
|
||||
use api\classes\API_users;
|
||||
use bin\php\Classes\mailBuilder;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_resetpassword.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/Classes/mailBuilder.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_users.php';
|
||||
|
||||
|
||||
$API_resetpassword = new API_resetpassword();
|
||||
|
||||
if ($API_resetpassword->request_method === 'GET') {
|
||||
|
||||
} elseif ($API_resetpassword->request_method === 'POST') {
|
||||
# Reset a users password and send a email to the user to set a new password
|
||||
|
||||
$API_resetpassword->checkPermissions('admin-access-admins-resetpassword', 'RW');
|
||||
|
||||
# The user will need to verify their email, the password field cannot be NULL so set an random password for now till the user resets it on when verifing there email
|
||||
$random_string = substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01', 64)), 0, rand(50, 64));
|
||||
$user_password = password_hash($random_string, PASSWORD_BCRYPT, ["cost" => 12]);
|
||||
$API_resetpassword->postedData['user_password'] = $user_password;
|
||||
|
||||
# Password reset token that will be send to the user
|
||||
$API_resetpassword->postedData['user_password_reset_token'] = bin2hex(random_bytes(32));
|
||||
$API_resetpassword->postedData['user_password_reset_expires'] = time() + 86400;
|
||||
|
||||
$requiredFields = [
|
||||
'user_uuid' => ['type' => 'uuid'],
|
||||
'user_password' => ['type' => 'string'],
|
||||
'user_password_reset_token' => ['type' => 'string'],
|
||||
'user_password_reset_expires' => ['type' => 'int'],
|
||||
];
|
||||
|
||||
$API_resetpassword->validateData($requiredFields);
|
||||
|
||||
$API_resetpassword->resetPassword();
|
||||
|
||||
$API_users = new API_users();
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'user_uuid', 1 => $API_resetpassword->data['user_uuid']]]];
|
||||
$user_data = $API_users->getUser()[0];
|
||||
|
||||
# Sending an email to the user
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$verifyLink = "https://{$host}/login/verifyEmail.php?token={$API_resetpassword->data['user_password_reset_token']}";
|
||||
|
||||
$mail = new mailBuilder();
|
||||
$mail->subject = "Hello " . $user_data['user_full_name'] . ", Here’s Your Password Reset Link";
|
||||
$mail->addAddress($user_data['user_email'], $user_data['user_first_name']);
|
||||
$mail->mailText = '
|
||||
Hello ' . $user_data['user_first_name'] . ',<br><br>
|
||||
|
||||
We received a request to reset the password for your account. As a security measure, your password has been reset.<br><br>
|
||||
|
||||
To set a new password of your choice, click the text below:<br>
|
||||
<a href="' . $verifyLink . '">Reset Password</a><br><br>
|
||||
|
||||
Or copy and paste the following link into your browser: <br>' . $verifyLink . '<br><br>
|
||||
|
||||
This link is valid for 24 hours from the time of this request.<br><br>
|
||||
|
||||
If you did not request this, you can safely ignore this email. No further action is required, and your account remains secure.<br><br>
|
||||
|
||||
Best regards,<br><br>
|
||||
The Sentri gnomes
|
||||
';
|
||||
|
||||
$mail->sendMail();
|
||||
$API_resetpassword->apiOutput(200, ['success' => 'Password reset link sent successfully.']);
|
||||
|
||||
} elseif ($API_resetpassword->request_method === 'PUT') {
|
||||
|
||||
} elseif ($API_resetpassword->request_method === 'DELETE') {
|
||||
|
||||
}
|
||||
100
pub/api/v1/vendors/index.php
vendored
Normal file
100
pub/api/v1/vendors/index.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
use api\classes\API_vendors;
|
||||
use api\classes\imageProcessor;
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/API_vendors.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/api/classes/imageProcessor.php';
|
||||
|
||||
$API_vendors = new API_vendors();
|
||||
|
||||
if ($API_vendors->request_method === 'GET') {
|
||||
|
||||
# get all the vendor
|
||||
|
||||
$API_vendors->checkPermissions('admin-vendors', 'RO');
|
||||
|
||||
} elseif ($API_vendors->request_method === 'POST') {
|
||||
|
||||
# create a new vendor
|
||||
|
||||
$API_vendors->checkPermissions('admin-vendors', 'RW');
|
||||
|
||||
try {
|
||||
$imageProcessor = new imageProcessor('vendor_image');
|
||||
$imageProcessor->imageRestrictions = [
|
||||
'min_width' => 200,
|
||||
'max_width' => 200,
|
||||
'min_height' => 200,
|
||||
'max_height' => 200,
|
||||
'square' => true,
|
||||
'allowed_types' => ['image/png'],
|
||||
'max_size_kb' => 1024
|
||||
];
|
||||
$imageProcessor->validateAndProcess();
|
||||
$finalImageData = $imageProcessor->returnBase64image();
|
||||
} catch (Exception $e) {
|
||||
$API_vendors->apiOutput(401, ['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
$API_vendors->postedData['vendor_image'] = $finalImageData;
|
||||
|
||||
$requiredFields = [
|
||||
'vendor_name' => ['type' => 'string'],
|
||||
'vendor_slugify' => ['type' => 'slugify'],
|
||||
'vendor_enabled' => ['type' => 'boolean'],
|
||||
'vendor_description' => ['type' => 'string'],
|
||||
];
|
||||
$optionalFields = ['vendor_image' => ['type' => 'string']];
|
||||
|
||||
$API_vendors->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$API_vendors->createVendor();
|
||||
|
||||
} elseif ($API_vendors->request_method === 'PUT') {
|
||||
|
||||
# edit a vendor
|
||||
|
||||
$API_vendors->checkPermissions('admin-vendors', 'RW');
|
||||
|
||||
try {
|
||||
$imageProcessor = new imageProcessor('vendor_image');
|
||||
$imageProcessor->imageRestrictions = [
|
||||
'min_width' => 200,
|
||||
'max_width' => 200,
|
||||
'min_height' => 200,
|
||||
'max_height' => 200,
|
||||
'square' => true,
|
||||
'allowed_types' => ['image/png'],
|
||||
'max_size_kb' => 1024
|
||||
];
|
||||
$imageProcessor->validateAndProcess();
|
||||
$finalImageData = $imageProcessor->returnBase64image();
|
||||
} catch (Exception $e) {
|
||||
$API_vendors->apiOutput(401, ['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
if ($finalImageData) {
|
||||
$API_vendors->postedData['vendor_image'] = $finalImageData;
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
'vendor_name' => ['type' => 'string'],
|
||||
'vendor_uuid' => ['type' => 'slugify'],
|
||||
'vendor_enabled' => ['type' => 'boolean'],
|
||||
'vendor_description' => ['type' => 'string'],
|
||||
];
|
||||
$optionalFields = ['vendor_image' => ['type' => 'string']];
|
||||
|
||||
$API_vendors->validateData($requiredFields, $optionalFields);
|
||||
|
||||
$_GET['builder'] = [1 => ['where' => [0 => 'vendor_uuid', 1 => $API_vendors->data['vendor_uuid']]]];
|
||||
$API_vendors->getVendors();
|
||||
|
||||
$API_vendors->editVendor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user