Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
b6d7def
fixed exporting config constants
cedricfrancoys Dec 6, 2022
16b5b31
removed refresh_token
cedricfrancoys Dec 6, 2022
07bb112
added DEFAULT_APP
cedricfrancoys Dec 6, 2022
94f00b4
added missing parts in packages folder
cedricfrancoys Dec 6, 2022
aafe719
added dependency for ZipArchive support
cedricfrancoys Dec 6, 2022
4848836
updated content
cedricfrancoys Dec 6, 2022
5ca4fba
added libzip to apt install
cedricfrancoys Dec 6, 2022
1837227
updates
cedricfrancoys Dec 10, 2022
77bd4ae
syntax
cedricfrancoys Dec 11, 2022
a3fb70b
changed Fields factory to Field abstract
cedricfrancoys Dec 11, 2022
27ae3f5
updated data adaptation logic
cedricfrancoys Dec 11, 2022
1d51b19
changed Usage files hierarchy
cedricfrancoys Dec 11, 2022
618afe9
comments
cedricfrancoys Dec 12, 2022
36f0f59
fixed sorting (moment instead of id)
cedricfrancoys Dec 12, 2022
f46394c
renamed numeric by number
cedricfrancoys Dec 12, 2022
906858b
added support for arrays
cedricfrancoys Dec 12, 2022
ffb7982
temp
cedricfrancoys Dec 12, 2022
359e6c0
adapt in methods
cedricfrancoys Dec 12, 2022
e249c24
added support for array notation + renamed numerci to number
cedricfrancoys Dec 12, 2022
e53a1fe
updates
cedricfrancoys Dec 12, 2022
d82cd0c
removed check on time
cedricfrancoys Dec 13, 2022
d5a2f13
added methods getTables and getTableSchema
cedricfrancoys Dec 13, 2022
154ac96
changed sql queries to generic db manager calls
cedricfrancoys Dec 13, 2022
70cc0ff
added sqlsrv non-standard types
cedricfrancoys Dec 13, 2022
53c7abc
added sqlsrv non-standard types
cedricfrancoys Dec 13, 2022
7e91ad2
updates
cedricfrancoys Dec 13, 2022
e50e189
updates
cedricfrancoys Dec 13, 2022
eff55b7
updates
cedricfrancoys Dec 13, 2022
6c387f1
updates
cedricfrancoys Dec 13, 2022
7c65e78
updates
cedricfrancoys Dec 13, 2022
464c5a4
updates
cedricfrancoys Dec 13, 2022
bc3cf69
updates
cedricfrancoys Dec 13, 2022
f803887
comments
cedricfrancoys Dec 16, 2022
11e597b
prevented self dependency in computed fields
cedricfrancoys Dec 19, 2022
f27e288
fixed constant definition not present in schema
cedricfrancoys Dec 19, 2022
6d31e9b
added square brackets to column name
cedricfrancoys Dec 19, 2022
dee2119
updated
cedricfrancoys Dec 20, 2022
62ab9e2
updated
cedricfrancoys Dec 20, 2022
1c6d117
updated
cedricfrancoys Dec 20, 2022
d46eb1b
updated
cedricfrancoys Dec 20, 2022
081333d
updated
cedricfrancoys Dec 20, 2022
fb2f74e
updated
cedricfrancoys Dec 20, 2022
dd313e5
added support for TNIR
cedricfrancoys Dec 20, 2022
6c0abbe
updates
cedricfrancoys Dec 21, 2022
5d9b5cd
updates
cedricfrancoys Dec 21, 2022
30ef7e2
updates
cedricfrancoys Dec 21, 2022
dfa5a89
updates
cedricfrancoys Dec 21, 2022
117b600
fixed getUserRights
cedricfrancoys Dec 22, 2022
e4a1588
chaged urgent to error
cedricfrancoys Dec 23, 2022
8d8ac37
added support for conventional optional alert field
cedricfrancoys Dec 23, 2022
191e483
syntax
cedricfrancoys Dec 23, 2022
1ce00a3
improved support for cache handling
cedricfrancoys Dec 23, 2022
cf9b73a
improved cache support + added cache-vary
cedricfrancoys Dec 24, 2022
dde455d
syntax
cedricfrancoys Dec 24, 2022
ca4b029
removed name from mandatory fields in Collection::read
cedricfrancoys Dec 24, 2022
cab1555
fix
cedricfrancoys Dec 24, 2022
b79dd54
fixed UTF8 chars handling
cedricfrancoys Jan 6, 2023
e3c2b31
syntax
cedricfrancoys Jan 6, 2023
a767949
comments
cedricfrancoys Jan 6, 2023
487755e
added support for cache
cedricfrancoys Jan 6, 2023
a54536e
added support for entity controllers
cedricfrancoys Jan 6, 2023
8537926
updates
cedricfrancoys Jan 6, 2023
b9f0ebc
updates
cedricfrancoys Jan 9, 2023
70e80cd
updates
cedricfrancoys Jan 9, 2023
5fff96a
syntax
cedricfrancoys Jan 9, 2023
df5fba1
added support for default parameters for custom controller
cedricfrancoys Jan 13, 2023
ba8aef3
fixed support for XSL date export
cedricfrancoys Jan 13, 2023
ec5f298
fixed empty domain support for conditionAdd
cedricfrancoys Jan 13, 2023
d0d5351
fixed custom controller calls
cedricfrancoys Jan 13, 2023
e9525bb
updates
cedricfrancoys Jan 16, 2023
e7d2f83
updates
cedricfrancoys Jan 16, 2023
4aa6f3e
fixed sections
cedricfrancoys Jan 16, 2023
0e4a720
updates
cedricfrancoys Jan 16, 2023
b76812e
updates
cedricfrancoys Jan 16, 2023
682d651
updates
cedricfrancoys Jan 16, 2023
6203900
fixed fields
cedricfrancoys Jan 16, 2023
b3a7c7c
added settings
cedricfrancoys Jan 16, 2023
47c75d4
updates
cedricfrancoys Jan 16, 2023
0036b2f
updates
cedricfrancoys Jan 16, 2023
03565d2
updates
cedricfrancoys Jan 16, 2023
07fa865
updates
cedricfrancoys Jan 16, 2023
14094c0
updates
cedricfrancoys Jan 16, 2023
07d3c50
updates
cedricfrancoys Jan 16, 2023
c11b36b
updates
cedricfrancoys Jan 16, 2023
035c5c5
updates
cedricfrancoys Jan 17, 2023
8c123bc
removed objects identifiers cache
cedricfrancoys Jan 18, 2023
3eeee03
syntax
cedricfrancoys Jan 18, 2023
cc6991d
fixed JS date formats
cedricfrancoys Jan 18, 2023
a61676c
added support for reading subobject from map
cedricfrancoys Jan 18, 2023
c32d73f
syntax
cedricfrancoys Jan 18, 2023
a852c24
syntax
cedricfrancoys Jan 18, 2023
58ae9cc
syntax
cedricfrancoys Jan 18, 2023
75cf553
syntax
cedricfrancoys Jan 18, 2023
9817691
data adaptation
cedricfrancoys Jan 18, 2023
e890e29
updates
cedricfrancoys Jan 19, 2023
0761828
updates
cedricfrancoys Jan 19, 2023
1befbd9
updates
cedricfrancoys Jan 19, 2023
d921d8e
updates
cedricfrancoys Jan 19, 2023
63ea410
added support for data adaptation based on usage
cedricfrancoys Jan 22, 2023
beae0b0
prepared for transition to Usage
cedricfrancoys Jan 22, 2023
2b912ba
added support for case non-sensitive type
cedricfrancoys Jan 23, 2023
ed40df2
fixed objects ids filtering
cedricfrancoys Jan 23, 2023
8916f90
comments
cedricfrancoys Jan 23, 2023
498bcaf
updates
cedricfrancoys Jan 25, 2023
f570df3
changed adapt notation from 'txt' to 'json' (#usagetransition)
cedricfrancoys Jan 28, 2023
92137b8
comments
cedricfrancoys Jan 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:

steps:
# install dependencies
- run: apt-get update && apt-get -y install git
- run: docker-php-ext-install pdo pdo_mysql mysqli
- run: apt-get update && apt-get -y install git libzip-dev
- run: docker-php-ext-install pdo pdo_mysql mysqli zip
- run: docker-php-ext-enable mysqli

- checkout:
Expand Down
9 changes: 3 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
vendor/
log/*
!log/.gitkeep
!log/.gitkeep
cache/*
!cache/.gitkeep
!cache/.gitkeep
spool/*
!spool/.gitkeep
bin/*
!bin/.gitkeep
config/config.inc.php
config/config.json
config/secrets.json
config/routing/*
!config/routing/.gitkeep
composer.phar
composer.lock
.vscode
packages
!packages/core
!packages/demo
public/*
!public/index.php
!public/console.php
!public/assets
public/assets/env/config.json
12 changes: 9 additions & 3 deletions config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
"instant": true,
"default": "core"
},
"DEFAULT_APP": {
"type": "string",
"description": "Default App to request from default package.",
"instant": true,
"default": "welcome"
},
"ROUTING_METHOD": {
"type": "string",
"description": "Method to use for parsing the URIs. Possible values are: 'ORM' or 'JSON' (router.json).",
Expand Down Expand Up @@ -136,21 +142,21 @@
},
"DB_PORT": {
"type": "integer",
"description": "TCP/IP port for connecting to DB host. Defaut ports: MYSQL 3306, SQLSRV 1433",
"description": "TCP/IP port for connecting to DB host. Default ports: MYSQL 3306, SQLSRV 1433",
"instant": true,
"environment": "EQ_DB_PORT",
"default": "3306"
},
"DB_USER": {
"type": "string",
"description": "Login for authentifying on DB host.",
"description": "Login for authenticating on DB host.",
"instant": true,
"environment": "EQ_DB_USER",
"default": "root"
},
"DB_PASSWORD": {
"type": "string",
"description": "Password for authentifying on DB host.",
"description": "Password for authenticating on DB host.",
"instant": true,
"environment": "EQ_DB_PASSWORD",
"default": "test"
Expand Down
135 changes: 91 additions & 44 deletions eq.lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ function export($property) {
// retrieve current value
$value = constant($property);
// handle shorthand notations
if($constants_schema[$property]['type'] == 'integer') {
if(isset($constants_schema[$property]) && $constants_schema[$property]['type'] == 'integer') {
// handle binary masks on arbitrary values or pre-defined constants
if(is_string($value) && (strpos($value, '|') !== false || strpos($value, '&') !== false)) {
try {
Expand All @@ -408,7 +408,7 @@ function export($property) {
$value = strtoint($value);
}
}
// handle crypted values
// handle encrypted values
elseif(is_string($value) && substr($value, 0, 7) == 'cipher:') {
$value = decrypt(substr($value, 7));
}
Expand Down Expand Up @@ -580,7 +580,7 @@ public static function announce(array $announcement) {
}
}

// set response headers
// check response headers
if(isset($announcement['response'])) {
if(isset($announcement['response']['location']) && !isset($body['announce'])) {
header('Location: '.$announcement['response']['location']);
Expand Down Expand Up @@ -633,17 +633,32 @@ public static function announce(array $announcement) {
/*
Caching is only available for GET methods,
and offers support at URL level only (params in body are not considered).
Controllers can use cache-vary to tell which elements influence their resulting content.
Accepted values for cache-vary array : uri (default), user, origin, body.

// #todo export this part of the logic to a cache manager
*/
if( $method == 'GET'
&& isset($announcement['response']['cacheable'])
&& $announcement['response']['cacheable']) {
list($auth) = $container->get(['auth']);
// compute the cache ID
// #todo - implement 'Vary' support - Vary: User, Uri, Cookie, User-Agent
$request_id = $auth->userId().'::'.$request->header('origin').'::'.$request->uri();
// remove 'cache' param from URI, if present
$request_id = trim(preg_replace('/&cache=[^&]*&/', '&', $request->uri().'&'), '&');
if(isset($announcement['response']['cache-vary'])) {
$vary = (array) $announcement['response']['cache-vary'];
if(in_array('user', $vary)) {
list($auth) = $container->get(['auth']);
$request_id .= '-'.$auth->userId();
}
if(in_array('origin', $vary)) {
$request_id .= '-'.$request->header('origin');
}
if(in_array('body', $vary)) {
$request_id .= '-'.$request->body();
}
}
$cache_id = md5($request_id);
// obtain related filename
// retrieve related filename
$cache_filename = QN_BASEDIR.'/cache/'.$cache_id;
// update context for further processing
$context->set('cache', true);
Expand All @@ -658,33 +673,51 @@ public static function announce(array $announcement) {
$expires = intval($announcement['response']['expires']);
$age = time() - filemtime(realpath($cache_filename));
if($age >= $expires) {
$reporter->debug("expired cache-id {$cache_id}");
$serve_from_cache = false;
}
}
// request is already present in cache and is valid : serve from cache
if(file_exists($cache_filename) && $serve_from_cache) {
// handle client cache expiry (no change)
if($request->header('If-None-Match') == $cache_id) {
// send "304 Not Modified"
$response
->status(304)
->send();
throw new \Exception('', 0);
// handle manual request for invalidating the cache
if(isset($body['cache'])) {
if(in_array($body['cache'], [null, false, 0, '0'])) {
$reporter->debug("manual reset cache-id {$cache_id}");
$serve_from_cache = false;
}
$reporter->debug("serving from cache");
list($headers, $result) = unserialize(file_get_contents($cache_filename));
// build response with cached headers
foreach($headers as $header => $value) {
$response->header($header, $value);
// cache is a reserved parameter: no further process
unset($body['cache']);
}
// request is already present in cache
if(file_exists($cache_filename)) {
// cache was invalidated: remove related file
if(!$serve_from_cache) {
$reporter->debug("invalidating cache-id {$cache_id}");
unlink($cache_filename);
}
// cache is still valid: serve from cache
else {
// handle client cache expiry (no change)
if($request->header('If-None-Match') == $cache_id) {
// send "304 Not Modified"
$response
->status(304)
->send();
throw new \Exception('', 0);
}
$reporter->debug("serving from cache-id {$cache_id}");
list($headers, $result) = unserialize(file_get_contents($cache_filename));
// build response with cached headers
foreach($headers as $header => $value) {
$response->header($header, $value);
}
$response
// inject raw body
->body($result, true)
// set status and body according to raised exception
->status(200)
// send HTTP response
->send();
exit();
}
$response
// inject raw body
->body($result, true)
// set status and body according to raised exception
->status(200)
// send HTTP response
->send();
exit();
}
}
}
Expand Down Expand Up @@ -742,31 +775,37 @@ public static function announce(array $announcement) {

// build mandatory fields array
foreach($announcement['params'] as $param => $config) {
if(isset($config['required']) && $config['required']) $mandatory_params[] = $param;
if(isset($config['required']) && $config['required']) {
$mandatory_params[] = $param;
}
}
// if at least one mandatory param is missing
$missing_params = array_values(array_diff($mandatory_params, array_keys($body)));
if( count($missing_params)
|| isset($body['announce'])
|| $method == 'OPTIONS' ) {
// no feedback about services
if(isset($announcement['providers'])) unset($announcement['providers']);
if(isset($announcement['providers'])) {
unset($announcement['providers']);
}
// no feedback about constants
if(isset($announcement['constants'])) unset($announcement['constants']);
if(isset($announcement['constants'])) {
unset($announcement['constants']);
}
// add announcement to response body
$response->body(['announcement' => $announcement]);
if(isset($body['announce']) || $method == 'OPTIONS') {
// user asked for the announcement or browser requested fingerprint
$response->status(200)
// allow browser to cache the response for 1 year
->header('Cache-Control', 'max-age=31536000')
// default content type and disposition
->header('Content-Type', 'application/json')
->header('Content-Disposition', 'inline')
// mandatory headers for CORS validation (OPTIONS request must have Content-Type explicitely set)
->header('Access-Control-Allow-Headers', 'Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Content-Type, Accept, X-Requested-With, Referrer-Policy, Referer, Cookie')
//->header('Access-Control-Allow-Headers', '*')
->send();
// allow browser to cache the response for 1 year
->header('Cache-Control', 'max-age=31536000')
// default content type and disposition
->header('Content-Type', 'application/json')
->header('Content-Disposition', 'inline')
// mandatory headers for CORS validation (OPTIONS request must have Content-Type explicitly set)
->header('Access-Control-Allow-Headers', 'Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Content-Type, Accept, X-Requested-With, Referrer-Policy, Referer, Cookie')
//->header('Access-Control-Allow-Headers', '*')
->send();
throw new \Exception('', 0);
}
// raise an exception with error details
Expand Down Expand Up @@ -801,7 +840,7 @@ public static function announce(array $announcement) {
$result[$param] = $adapter->adapt($body[$param], $config['type']);
/*
// convert value from input format + validate type and usage constraints
$f = Fields::create($config);
$f = new Field($config);
// raises an Exception if assignment is not possible
$f->set($body[$param], 'json'); // not explicit type, but Content-Type from HTTP REQUEST
try {
Expand Down Expand Up @@ -902,11 +941,11 @@ public static function announce(array $announcement) {
foreach($announcement['constants'] as $name) {
if(defined($name) && !\defined($name)) {
$value = constant($name);
// handle crypted values
// handle encrypted values
if(is_string($value) && substr($value, 0, 7) == 'cipher:') {
$value = decrypt(substr($value, 7));
}
\define($name, $value);
export($name, $value);
}
if(!\defined($name)) {
throw new \Exception("Requested constant {$name} is missing from configuration", QN_ERROR_INVALID_CONFIG);
Expand Down Expand Up @@ -1063,6 +1102,8 @@ public static function run($type, $operation, $body=[], $root=false) {
}

// force timezone to UTC
// #memo - this is to (avoid being impacted by daylight saving offset
// #memo - we expect the DBMS to store dates in UTC as well
date_default_timezone_set('UTC');

if(!$root) {
Expand All @@ -1083,6 +1124,8 @@ public static function run($type, $operation, $body=[], $root=false) {
$context->httpResponse()->header('Etag', $cache_id);
$headers = $context->httpResponse()->headers()->toArray();
file_put_contents(QN_BASEDIR.'/cache/'.$cache_id, serialize([$headers, $result]));
$reporter = $container->get('report');
$reporter->debug("stored cache-id {$cache_id}");
}
}
trigger_error("QN_DEBUG_PHP::result - $result", QN_REPORT_DEBUG);
Expand Down Expand Up @@ -1204,6 +1247,10 @@ public static function run($type, $operation, $body=[], $root=false) {
return $data;
}

public static function announce(array $announcement) {
return config\eQual::announce($announcement);
}

public static function inject(array $providers) {
return config\eQual::inject($providers);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/equal/access/AccessController.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ protected function getUserRights($user_id, $object_class, $object_fields=[], $ob
return QN_R_CREATE | QN_R_READ | QN_R_WRITE | QN_R_DELETE | QN_R_MANAGE;
}
else {
$orm = $this->container->get('orm');

// get user groups
$groups_ids = $this->getUserGroups($user_id);
Expand All @@ -109,7 +110,6 @@ protected function getUserRights($user_id, $object_class, $object_fields=[], $ob
}
}
else {
$orm = $this->container->get('orm');

$domains = [];
// add parent classes to the domain (when a right is granted on a class, it is also granted on children classes)
Expand Down
26 changes: 12 additions & 14 deletions lib/equal/cron/Scheduler.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public static function constants() {
* Runs a batch of scheduled tasks.
*
* At each call we check all active tasks and execute the ones having the `moment` field (timestamp) overdue.
* For recurring tasks we update the moment field to the next time, accoring to repeat axis and repeat step.
* For recurring tasks we update the moment field to the next time, according to repeat axis and repeat step.
* Non-recurring tasks are deleted once they've been run.
*
* #memo - Scheduler always operates as root user.
*/
public function run() {
$orm = $this->container->get('orm');

$tasks_ids = $orm->search('core\Task', ['is_active', '=', true], ['id' => 'asc'], 0, 10);
$tasks_ids = $orm->search('core\Task', ['is_active', '=', true], ['moment' => 'asc'], 0, 10);

if($tasks_ids > 0) {
$now = time();
Expand All @@ -48,7 +48,7 @@ public function run() {
\eQual::run('do', $task['controller'], $body, true);
}
catch(\Exception $e) {
// error occured during execution
// error occurred during execution
}
// update task, if recurring
if($task['is_recurring']) {
Expand All @@ -75,21 +75,19 @@ public function run() {
*/
public function schedule($name, $moment, $controller, $params, $recurring=false, $repeat_axis='day', $repeat_step='1') {
$orm = $this->container->get('orm');
trigger_error("scheduling job", E_USER_WARNING);
trigger_error("scheduling job", QN_REPORT_INFO);

if($moment > time()) {
$orm->create('core\Task', [
'name' => $name,
'moment' => $moment,
'controller' => $controller,
'params' => json_encode($params),
'is_recurring' => $recurring
]);
}
$orm->create('core\Task', [
'name' => $name,
'moment' => $moment,
'controller' => $controller,
'params' => json_encode($params),
'is_recurring' => $recurring
]);
}

/**
* Cancels (delete) a scheduled task.
* Cancels a scheduled task (by deleting it).
* #memo - Scheduler always operates as root user.
*
* @param string $name Name of the task to cancel.
Expand Down
Loading