Skip to content

Commit

Permalink
Merge branch 'develop' into feature/FormBannerSupport
Browse files Browse the repository at this point in the history
  • Loading branch information
2piJareem authored Aug 16, 2023
2 parents d1eef8f + a94bcea commit 6d6056a
Show file tree
Hide file tree
Showing 14 changed files with 409 additions and 20 deletions.
4 changes: 3 additions & 1 deletion system/classes/html/form/inputfield/DatetimeLocal.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

/**
* A helper InputField class for datetime-local, extends the datetime class for
* the time being as browser support for datetime-local is very poor.
* the time being (as)/(in case?) browser support for datetime-local is very poor.
*
* @author Adam Buckley <[email protected]>
*/
class DatetimeLocal extends \Html\Form\InputField\Datetime {

public $type = "datetime-local";

}
2 changes: 2 additions & 0 deletions system/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,5 @@
'secret' => '',
],
]);

Config::set('system.use_api', true);
2 changes: 1 addition & 1 deletion system/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ function defaultVal($val, $default = null)
*/
function toSlug($title)
{
return strtolower(str_replace([' ', '_', ',', '.', '/'], '-', $title));
return strtolower(str_replace([' ', '_', ',', '.', '/'], '-', ($title ?? "")));
}

/**
Expand Down
16 changes: 8 additions & 8 deletions system/html.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public static function ab($href, $title, $class = "", $id = "", $confirm = "")
/**
* Create an a link styled as a button that pops up a reveal dialog
* */
public static function abox($href, $title, $class = null, $id = null, $confirm = null)
public static function abox($href, $title, $class = "", $id = "", $confirm = "")
{
$classParam = ' button tiny ';
if (strlen($class) > 0) {
Expand Down Expand Up @@ -365,8 +365,8 @@ public static function form($data, $action = null, $method = "POST", $submitTitl
$readonly = "";

// handle disabled fields
if (substr($name, 0, 1) == '-') {
$name = substr($name, 1);
if (substr(($name ?? ""), 0, 1) == '-') {
$name = substr(($name ?? ""), 1);
$readonly = " readonly='true' ";
}
// Add title field
Expand Down Expand Up @@ -665,8 +665,8 @@ public static function multiColForm($data, $action = null, $method = "POST", $su
$buffer .= ($type !== "hidden" ? "<div>" : "");

// handle disabled fields
if (substr($name, 0, 1) == '-') {
$name = substr($name, 1);
if (substr(($name ?? ""), 0, 1) == '-') {
$name = substr(($name ?? ""), 1);
$readonly = " readonly='true' ";
}

Expand Down Expand Up @@ -969,7 +969,7 @@ public static function autocomplete($name, $options, $value = null, $class = nul
}
}
// Remove trailing comma
$source = substr($source, 0, -1);
$source = substr(($source ?? ""), 0, -1);
$source .= "]";
} else {
$source = "'" . $options . "'";
Expand Down Expand Up @@ -1335,8 +1335,8 @@ public static function filter($legend, $data, $action = null, $method = "POST",
}

// handle disabled fields
if (substr($name, 0, 1) == '-') {
$name = substr($name, 1);
if (substr(($name ?? ""), 0, 1) == '-') {
$name = substr(($name ?? ""), 1);
$readonly = " readonly='true' ";
}

Expand Down
52 changes: 49 additions & 3 deletions system/modules/auth/models/AuthService.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ public function login($login, $password, $client_timezone, $skip_session = false
}
public function externalLogin($login, $password, $skip_session = false)
{

$user = $this->getUserForLogin($login);
if (empty($user->id) || ($user->encryptPassword($password) !== $user->password) || $user->is_external == 0) {
return null;
Expand Down Expand Up @@ -257,7 +256,7 @@ public function getContacts()
*
* @return array[Lookup]
*/
public function getTitles() : array
public function getTitles(): array
{
return LookupService::getInstance($this->w)->getLookupByType("title");
}
Expand Down Expand Up @@ -328,11 +327,51 @@ public function allowed($path, $url = null)
return false;
}

// Whitelisted action, or white-bread login session
if ((function_exists("anonymous_allowed") && anonymous_allowed($this->w, $path)) || ($this->user() && $this->user()->allowed($path))) {
self::$_cache[$key] = $url ? $url : true;
return self::$_cache[$key];
}

// API token handling:
// If I have an authentication header: and it has a token -> else fallthrough to original logic
// ie: expecting [...curl...etc...] -H "Authorization: Bearer {token}"
/*
Note! If under Apache & HTTP_AUTHORIZATION is dropped, prove site HTPPS and then patch access:
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
*/

if (empty($this->user()) && (Config::get('system.use_api') === true) && !empty($_SERVER['HTTP_AUTHORIZATION'])) {
$speculativeToken = TokensService::getInstance($this->w)->getTokenFromAuthorisationHeader($_SERVER['HTTP_AUTHORIZATION']);
if (!empty($speculativeToken)) {
// call for a module to assert the token is valid
$hook_results = $this->w->callHook("auth", "get_auth_token_validation", $speculativeToken);
}

// if the token is invalid( jwt fails checks, len == 0 or somesuch) then we stop and don't continue
if (empty($speculativeToken) || empty($hook_results)) {
LogService::getInstance($this->w)->error("Key invalid: '" . ($_SERVER['HTTP_AUTHORIZATION'] ?? "!NONE!") . "' was provided");
ApiOutputService::getInstance($this->w)->apiRefuseMessage($path,"Token not valid");
self::$_cache[$key] = false;
return false;
}
foreach ($hook_results as $module => $validatingToken) {
if (is_a($validatingToken, "TokensPolicy") && $validatingToken->tokensAllowed($path)) {
self::$_cache[$key] = $url ? $url : true;
return self::$_cache[$key];
} else {
LogService::getInstance($this->w)->info('Handler ' . $module . ' did not provide Auth');
}
}
ApiOutputService::getInstance($this->w)->apiRefuseMessage($path.":[".$speculativeToken."]", "Token not authenticated");
self::$_cache[$key] = false;
return false;
}


// Allow forced user-login if any module will vouch for web server asserted identity
if (empty($this->user()) && (Config::get('system.use_passthrough_authentication') === true) && !empty($_SERVER['AUTH_USER'])) {
// Get the username
$username = explode('\\', $_SERVER["AUTH_USER"]);
Expand All @@ -346,6 +385,13 @@ public function allowed($path, $url = null)
$this->forceLogin($user->id);
if ($user->allowed($path)) {
self::$_cache[$key] = $url ? $url : true;
// Observed during work for token handler:
// Here, we have forced login,
// But do we mean for it to still bounce 1x through auth/login as redirect?
// In standing core releases, a _cache[key] 'return' is omitted here
// = noting it was required by new tokens model!
// Possibly this block should also have return thus:
// return self::$_cache[$key];
}
} else {
LogService::getInstance($this->w)->info($module . ' did not provide passthrough user for:' . $username);
Expand All @@ -362,7 +408,7 @@ public function allowed($path, $url = null)
*
* @return array of strings
*/
public function getAllRoles() : array
public function getAllRoles(): array
{
$this->_loadRoles();
if (!$this->_roles) {
Expand Down
24 changes: 21 additions & 3 deletions system/modules/file/actions/admin/moveToAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ function moveToAdapter_GET(Web $w)
{
$from_adapter = Request::string('from_adapter');
$to_adapter = Request::string('to_adapter');
$max_count = Request::string('max_count');

if (empty($max_count)) {
$max_count = -1;
}

if (!empty(Config::get('file.adapters.' . $to_adapter)) && Config::get('file.adapters.' . $to_adapter . '.active') === true) {
if (empty(Config::get('file.adapters.' . $from_adapter))) {
Expand All @@ -12,14 +17,27 @@ function moveToAdapter_GET(Web $w)

// From index
$count = 0;
$skipped = 0;
$attachments = FileService::getInstance($w)->getAttachmentsForAdapter($from_adapter);
if (!empty($attachments)) {
foreach ($attachments as $attachment) {
$attachment->moveToAdapter($to_adapter);
$count++;
if ($max_count >= 0 && $count >= $max_count) {
break;
}
try {
$attachment->moveToAdapter($to_adapter);
$count++;
} catch (Exception $e) {
LogService::getInstance($w)->error($e->getMessage());
$skipped++;
}
}
}
$w->msg($count . ' attachment' . ($count == 1 ? '' : 's') . ' moved from "' . $from_adapter . '" to "' . $to_adapter . '"', '/file-admin');
$message = ($count . ' attachment' . ($count == 1 ? '' : 's') . ' moved from "' . $from_adapter . '" to "' . $to_adapter . '"');
if ($skipped > 0) {
$message = $message . ('<br>' . $skipped . ' attachment' . ($skipped == 1 ? '' : 's') . ' skipped, check logs.');
}
$w->msg($message, '/file-admin');
} else {
$w->error('Target adapter "' . $to_adapter . '" is either not found or not active', '/file-admin');
}
Expand Down
4 changes: 2 additions & 2 deletions system/modules/file/models/Attachment.php
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,8 @@ public function updateAttachment($requestkey)
if ($this->isImage()) {
// Generate thumbnail and cache
require_once 'phpthumb/ThumbLib.inc.php';
$width = $this->w->request("w", FileService::$_thumb_width);
$height = $this->w->request("h", FileService::$_thumb_height);
$width = Request::int('w', FileService::$_thumb_width);
$height = Request::int('h', FileService::$_thumb_height);
$thumb = PhpThumbFactory::create($this->getContent(), [], true);
$thumb->adaptiveResize($width, $height);

Expand Down
10 changes: 10 additions & 0 deletions system/modules/tokens/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
Config::set('tokens', array(
'active' => true,
'path' => 'system/modules',
'topmenu' => false,
'hooks' => [
'auth',
'tokens'
],
));
101 changes: 101 additions & 0 deletions system/modules/tokens/models/ApiOutputService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/**@author Derek Crannaford */

class ApiOutputService extends DbService
{
// This function, having no apparent need for elaboration
// was retired for feature into 8.1, beware if you used it externally!
// public function useNoTemplate($w)
// {
// $w->setLayout(null);
// }

public function apiReturnCmfiveStyledHtml($w, $response)
{
$w->setLayout("layout-modal");
$w->enqueueScript(
[
"name" => "main.js", "uri" => "/system/templates/js/main.js", "weight" => 995
]
);
$w->enqueueStyle(
[
"name" => "foundation.css", "uri" => "/system/templates/js/foundation-5.5.0/css/foundation.css", "weight" => 1005
]
);
// $w->enqueueStyle(array("name" => "style.css", "uri" => "/system/templates/css/style.css", "weight" => 1000));
// $w->outputStyles();
// $w->outputScripts();
$w->out($response);
echo $w->_buffer;
exit(0);
}

public function apiReturnJsonResponse($response)
{
$this->w->setLayout(null);
http_response_code($response['status']);
// mark header for return content type JSON
if (substr($response['status'], 0, 1) == "2") {
header('Content-Type: application/json');
} else {
LogService::getInstance($this->w)->info("API request rejected: " . $response['referer']);
// Don't need, already have set response code!
// header($_SERVER["SERVER_PROTOCOL"] . " " . $response['status'] . " " . $response['payload'][0]);
}

echo json_encode(['response' => $response]);
exit(0);
}

// JSON simple message
public function apiKeyedResponse($payload = [], $message = "Success", $status_code = "200")
{
$success = [
'status' => $status_code,
'message' => $message,
'payload' => $payload
];
$this->apiReturnJsonResponse($success);
}

// JSON simple message
public function apiSimpleResponse($detail = "", $message = "Success", $status_code = "200")
{
$payload[] = $detail;
$success = [
'status' => $status_code,
'message' => $message,
'payload' => $payload
];
$this->apiReturnJsonResponse($success);
}

// JSON nice fail message
public function apiFailMessage($source = "", $detail = "", $message = "Failure", $status_code = "500")
{
$payload[] = $detail;
$errors = [
'status' => $status_code,
'referer' => $source,
'message' => $message,
'payload' => $payload
];
$this->apiReturnJsonResponse($errors);
}

// JSON nice refuse message
public function apiRefuseMessage($source = "", $detail = "", $message = "Unauthorised", $status_code = "403")
{
$payload[] = $detail;
$errors = [
'status' => $status_code,
'referer' => $source,
'message' => $message,
'payload' => $payload
];

$this->apiReturnJsonResponse($errors);
}
}
Loading

0 comments on commit 6d6056a

Please sign in to comment.