summaryrefslogtreecommitdiff
path: root/public/app/controllers
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-05-04 03:02:01 +0300
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-05-04 03:02:01 +0300
commit63f714d5a78b765c117ebf6bbdfdbd748dd45644 (patch)
tree87a4db40e1ff699222ccfdf699a3904d1c665bfc /public/app/controllers
parent931a93cd7bae092e2752064568cebe407d2bf46e (diff)
downloadgyraf1gov-63f714d5a78b765c117ebf6bbdfdbd748dd45644.tar.gz
gyraf1gov-63f714d5a78b765c117ebf6bbdfdbd748dd45644.tar.bz2
gyraf1gov-63f714d5a78b765c117ebf6bbdfdbd748dd45644.zip
authentication; invitation; activation; base form setup
Diffstat (limited to 'public/app/controllers')
-rw-r--r--public/app/controllers/Auth.php280
-rw-r--r--public/app/controllers/Cms.php259
-rw-r--r--public/app/controllers/JsonToForm.php89
-rw-r--r--public/app/controllers/Office.php424
4 files changed, 593 insertions, 459 deletions
diff --git a/public/app/controllers/Auth.php b/public/app/controllers/Auth.php
index 4b3dcfb..118b4d0 100644
--- a/public/app/controllers/Auth.php
+++ b/public/app/controllers/Auth.php
@@ -5,8 +5,9 @@ use Registry;
use Render;
// user classes and models
-use app\extends\Classroom_user;
-use app\extends\Classroom_manager;
+use app\controllers\JsonToForm;
+use app\extends\App_user;
+use app\extends\App_manager;
use app\models\Access_model;
use app\extends\SendMail_service;
@@ -37,50 +38,40 @@ class Auth {
// user is valid; check user password
// create a user object
- $user = (new Classroom_user())
+ $user = (new App_user())
->setID($record['id'])
+ ->setSex( ($record['prefix'] == 'η') ? 2 : 1 )
->setUserName($record['email'])
->setName($record['first_name'] .' '. $record['last_name'])
->setPassword($record['password'])
+ ->setRoles([ $record['role_id'] ]) // roles is an array
->setEnabled($record['active']);
+
// let user manager to validate user credentials
- $userManager = new Classroom_manager();
+ $userManager = new App_manager();
if ($userManager->isPasswordValid($user, $req->POST['password'])) {
- // get user's security attributes
- $attributes = Access_model::getUser($record['id']);
- $roles = json_decode($attributes['Roles_json']);
- $user
- ->setRoles($roles)
- ->setPrivileges(
- array_merge(
- json_decode($attributes['RootPrivileges_json']),
- self::merge_lists_array(
- json_decode($attributes['SubPrivileges_json'])
- )
- )
- );
-
// regeneration session ID (prevent session fixation)
+ session_unset(); // unset $_SESSION variable for the run-time
+ session_destroy(); // destroy session data in storage before continue
+ session_start();
session_regenerate_id();
+
// set cookie for connected user
setcookie(
- 'cluser',
+ CONNECTION_COOKIE,
'connected;'. $user->getName(),
- time()+60*60*8, // 8 hours
+ time()+60*60*10, // 10 hours
'/'
);
-
- // check if admin (and redirect differently)
- $is_admin = (!empty(array_intersect([1,2,3], $roles)));
-
+
// login OK, set Token in session
$userManager->createUserToken($user);
return [
'success' => true,
- 'goto' => $is_admin ? '/admin/lessons' : '/user/profile',
+ 'goto' => '/admin/panel'
];
} else {
@@ -89,33 +80,27 @@ class Auth {
}
- /**
- * merges an array of lists to one list
- */
- private static function merge_lists_array( $list )
- {
- $current = [];
- foreach($list as $sublist) {
- $current = array_merge($current, $sublist);
- }
- return $current;
- }
-
-
/** activate
- * resolves a call like: /account/activate?ticket=ca42d68cfba5fbbafeacc010b8e3a551
+ * resolves call POST:/account/activate
+ *
+ * @param void : all parametres passed via request->POST
*/
public static function activate()
{
$req = Registry::get('REQUEST');
+ // print_r($req->POST); die();
- // get the record of the target user
- $check = Access_model::activate($req->GET['ticket']);
+ // create a salted password hash
+ $userManager = new App_manager();
+ $password = $userManager->cryptPassword($req->POST['password']);
- if ($check == true) {
+ // acivate target user and set password
+ $check = Access_model::activate_set_password($req->POST, $password);
+
+ if ($check != 0) {
Render::view('/error/general', [
'title' => ACCOUNT_ACTIVATED_TITLE,
- 'message' => ACCOUNT_ACTIVATED_MESSAGE
+ 'message' => ACCOUNT_ACTIVATED_MESSAGE . '<br>(msg code: '. $check .')'
]);
} else {
@@ -127,64 +112,72 @@ class Auth {
}
- /** register
+
+ /** invitation
+ *
+ * setups and renders the form for a certain invitation
+ *
+ * NOTE:
+ * after form is submited, client calls Auth::activate()
*
- * Method for new user registration
+ * @param $id (string|MD5) : invitation code
*
*/
- public static function register()
+ public static function invitation($id)
{
- $userManager = new Classroom_manager();
- $req = Registry::get('REQUEST');
+ // get user from invitation number
+ $user_array = Registry::use('database')->query(
+ "SELECT * FROM user WHERE invitation = :id",
+ ['id' => $id]
+ )->getFirst();
+ if ($user_array == false) {
+ Render::view('error/404', ['moto' => 'Δεν βρέθηκε η πρόσκληση']);
+ die();
+ }
+ $user = json_decode( json_encode($user_array, JSON_UNESCAPED_UNICODE)); // user in json format
- // create a salted password hash
- $password = $userManager->cryptPassword($req->POST['password']);
+ // format form_setup to a json array
+ $form_setup = json_decode(json_encode(REGISTRATION_FORM, JSON_UNESCAPED_UNICODE));
- // echo $password; print_r($req->POST); die(); // OK!
-
- $user = (new Classroom_user())
- ->setUserName($req->POST['email'])
- ->setName($req->POST['name'] .' '. $req->POST['surname'])
- ->setPassword($password)
- ->setRoles([ READER ]) // Role: authorized reader
- ->setPrivileges([]); // none privilege until acount confirmation
-
- // create user record
- $activation_code = Access_model::registerUser($req->POST, $password);
-
- // TODO:
- // handle error on user registration
- // ...
- //
- // if ($activatopn_code[] == -1) {
- // return [
- // 'success' => false,
- // 'message' => REGISTRATION_USER_EXISTS
- // ];
- // }
-
- $send_mail = SendMail_service::send_activation_code([
- 'email' => $req->POST['email'],
- 'name' => $req->POST['name'] .' '. $req->POST['surname'],
- 'code' => $activation_code['activation']
- ]);
+ // get $key of position item inside the form_setup->form array
+ for($i=0; $i < sizeof($form_setup->form) ; $i++) {
+ if ($form_setup->form[$i]->name == 'position') { $key = $i; }
+ }
- // Send replies
- if ($send_mail) {
- return [
- 'success' => true,
- 'message' => REGISTRATION_SUCCESS
+ // prepare gendered options to position field
+ $positions = ($user->prefix != 'η')
+ ? [
+ 'Διευθυντής',
+ 'Υποδιευθυντής',
+ 'Μόνιμος Καθηγητής',
+ 'Αναπληρωτής Καθηγητής'
+ ]
+ : [
+ 'Διευθύντρια',
+ 'Υποδιευθύντρια',
+ 'Μόνιμη Καθηγήτρια',
+ 'Αναπληρώτρια Καθηγήτρια'
];
+ $gendered_position = json_decode( json_encode( $positions, JSON_UNESCAPED_UNICODE ));
- } else {
- return [
- 'success' => false,
- 'message' => 'error on sending email'
- ];
- }
+ // attach gendered options
+ $form_setup->form[$key]->options = $gendered_position;
+
+ // attach default values
+ $form_setup->defaults->values = $user;
+
+ // get Form's HTML and Jsvascript
+ $form = JsonToForm::json_form($form_setup, [
+ // pass invitation identity for security
+ ['name' => 'id', 'value' => $user->id],
+ ['name' => 'invitation', 'value' => $user->invitation]
+
+ ]);
+ Render::view('user/invitation', ['form' => $form]);
}
+
/** is_connected
* checks if the user is connected
*
@@ -192,7 +185,7 @@ class Auth {
*/
public static function is_connected()
{
- $manager = new Classroom_manager();
+ $manager = new App_manager();
if ($manager->hasUserToken()) {
// user is connected;
@@ -215,16 +208,19 @@ class Auth {
*/
public static function logout()
{
- $userManager = new Classroom_manager();
+ $userManager = new App_manager();
$userManager->logout();
// regeneration session ID (prevent session fixation)
+ session_unset(); // unset $_SESSION variable for the run-time
+ session_destroy(); // destroy session data in storage before continue
+ session_start();
session_regenerate_id();
// remove user-conected cookie
- if (isset($_COOKIE['cluser'])) {
- unset($_COOKIE['cluser']);
- setcookie('cluser', '', -1, '/');
+ if (isset($_COOKIE[CONNECTION_COOKIE])) {
+ unset($_COOKIE[CONNECTION_COOKIE]);
+ setcookie(CONNECTION_COOKIE, '', -1, '/');
return true;
} else {
@@ -233,97 +229,27 @@ class Auth {
}
-
- /** hasPermition( PERMIT )
- *
- * checks if the user owns the specified permition
- * to access the source
+ /** TODO:
*
*/
- public static function hasPermition($permit = [0])
+ public static function forgot_password()
{
- if (in_array(0, $permit)) { // permision 0 means public
- return true; // permision 0 is always granted
- }
-
- if ($user = self::is_connected() === false) { // if not connected
- return false; // then no other permition is granted
- }
-
- if ($user instanceof UserInterface) {
- return ( !empty( array_intersect($permit, $user->getPrivileges()) ) );
- }
}
- /** isAuthenticated()
- *
- * chechs if the user's roles and permitions
- * satisfy the specified requirements
- * to access the source
- *
- * @param $requirements (array of rules-array)
- *
- * example:
- * [
- * [
- * role => [2, 3]
- * permition => ['10', '12', '18']
- * ],
- * [
- * role => [1 , 4]
- * ],
- * [
- * permition => [ 3 ]
- * ]
- * ]
- *
- * defines (and parses to) a requirements rule of:
- * [
- * user should be creator or editor
- * _AND_ have permition 10 or 12 or 18
- * ]
- * OR
- * [
- * user should be an administrator or developer
- * ]
- * OR
- * [
- * user should have permition #3
- * ]
- *
+ /** TODO:
*
*/
- public static function isAuthorized($requirements)
- {
- $authorized = false;
- foreach($requirements as $required) {
-
- if (isset($required['role'])) { // if a role is required
- if ( (self::isGranted($required['role'])) // authorize both role
- && (self::hasPermition($required['permition'] ?? [ 0 ])) ) { // and permition
- // $authorized = true;
- return true;
- }
-
- } else { // else, if not is not required
- if (self::hasPermition($required['permition'] ?? [ 0 ])) { // authorize permition
- // $authorized = true;
- return true;
- }
- }
- }
- return $authorized;
- }
-
-
- public static function forgot_pass()
+ public static function validate_otp()
{
}
- public static function validate_otp()
+ /** TODO:
+ *
+ */
+ public static function reset_password()
{
}
@@ -339,7 +265,7 @@ class Auth {
*/
public static function allowRoles($allowed)
{
- $manager = new Classroom_manager();
+ $manager = new App_manager();
if ($manager->isGranted($allowed)) { // if valid, return true (continue)
return true;
@@ -361,21 +287,17 @@ class Auth {
*/
public static function hasValidRole($allowed)
{
- $manager = new Classroom_manager();
+ $manager = new App_manager();
return ($manager->isGranted($allowed));
}
public static function in_admin_group()
{
- $manager = new Classroom_manager();
+ $manager = new App_manager();
return ($manager->isGranted([1, 2, 3]));
}
}
-
-
-// NOTE:
-// check: https://netcorecloud.com/tutorials/send-an-email-via-gmail-smtp-server-using-php/ \ No newline at end of file
diff --git a/public/app/controllers/Cms.php b/public/app/controllers/Cms.php
deleted file mode 100644
index 306bc88..0000000
--- a/public/app/controllers/Cms.php
+++ /dev/null
@@ -1,259 +0,0 @@
-<?php
-
-namespace app\controllers;
-
-use Registry;
-use Render;
-use app\controllers\Auth;
-use app\models\Cms_model;
-use app\extends\Cache_service;
-
-/** CMS class
- * (Content Management System)
- *
- * Serves the content;
- * Reponds to all front-end front-office requests
- *
- */
-class Cms {
-
-
- ## PERMITION
- ## -------------------------------------------------------------------------
-
-
- /** is admin or permited
- *
- * shortcut method for checking access authorization
- *
- * returns true if user belogns to the admin group
- * OR has the specified permition/privilege
- *
- * @param $privilege_id (int)
- *
- * NOTE:
- * unlike the other authorization methods ...
- * $privilege_id is NOT an array but a single privilege id
- *
- * @return true|false
- */
- private static function is_admin_or_permited( $privilege_id )
- {
- return (
- Auth::in_admin_group()
- || Auth::hasPermition([ $privilege_id ])
- );
- }
-
-
-
- ## FILES
- ## -------------------------------------------------------------------------
-
-
- /** serve file by file_path
- * (request is valid only for admin users)
- *
- * @param $file_path (string): relative file path
- * GET @param type (string) : media-type of file
- */
- public static function serve_file($file_path)
- {
- $file = self::get_file_attributes($file_path);
-
- // if user is authorized
- if (self::is_admin_or_permited($file['privilege_id'])) {
-
- $media_type = Registry::get('REQUEST')->GET['type']; // get media-type
- $real_path = MEDIA_STORAGE_ROOT . $file_path; // construct real path
-
- if (!file_exists($real_path)) {
- Render::view('error/404');
-
- } else {
- Render::file($real_path, $media_type);
- }
-
- } else {
- Render::view('error/404', [
- 'error_code' => 403,
- 'moto' => 'Forbidden',
- 'message' => ''
- ]);
- }
- }
-
-
- /** get_file_attributes
- *
- * returns attributes of a file
- * (medias are proxied for speed optimization)
- *
- * @param $path (string) : file path
- * @return $file attributes --or-- false
- */
- private static function get_file_attributes($path)
- {
- $medias = Cache_service::files_attributes();
-
- foreach($medias as $key => $medi) {
-
- if ($medi['path'] == $path) {
-
- return $medi;
- }
- }
-
- return false;
- }
-
-
-
- ## COURSES
- ## -------------------------------------------------------------------------
-
-
- /** course
- * prepare and render the course view
- *
- * @param $id : course id
- */
- public static function course($id)
- {
- $id = intval($id); // course id
-
- // collect all data needed for course view
- // --- -- -- - - -
- $cache = Cache_service::courses_struct();
- $tree = $cache['tree'];
- $breadcrumbs = $cache['breadcrumbs'];
- $lessons = Cms_model::lessons_of_course(intval($id));
-
- // find parent_ids of current category (to open the menu tree)
- // ---
- $course_path = [];
- foreach($breadcrumbs[$id]['parents'] as $key => $parent) {
- $course_path[] = intval($parent['id']);
- }
- $course_path[] = $id;
-
- // then Render
- // --- -- -- - - -
- Render::view('templates/course', [
- 'id' => $id,
- 'title' => $breadcrumbs[ $id ]['rec']['label'],
- 'categories' => $tree,
- 'breadcrumbs' => $breadcrumbs,
- 'lessons' => $lessons,
- 'course_path' => $course_path,
- // needed by footer
- 'entity' => Cache_service::pages_list()
- ]);
- }
-
-
-
- ## LESSONS
- ## -------------------------------------------------------------------------
-
-
-
- /** lesson
- *
- * check if user is authorized to view the content;
- * if so, prepare and render the lesson view
- *
- * @param $id : lesson id
- */
- public static function lesson($id)
- {
- $id = intval($id); // lesson id
-
- $lesson = Cms_model::lesson($id); // get lesson
- $course_id = $lesson['course_id']; // get course id
- $pri_id = $lesson['privilege_id']; // privilege needed
-
-
- if (self::is_admin_or_permited($pri_id)) {
-
- // collect all data needed for course view
- // --- -- -- - - -
- $cache = Cache_service::courses_struct();
- $tree = $cache['tree'];
- $breadcrumbs = $cache['breadcrumbs'];
-
- // find parent_ids of current category (to open the menu tree)
- // ---
- $course_path = [];
- foreach($breadcrumbs[$course_id]['parents'] as $key => $parent) {
- $course_path[] = intval($parent['id']);
- }
- $course_path[] = intval($course_id);
-
- // NOTE: CRITICAL:
- // do not pass Class::method directly to the eported variables
- // $entity = Cache_service::pages_list();
-
- // var_dump($entity); die();
-
- // then Render
- // --- -- -- - - -
- Render::view('templates/lesson', [
- // main content
- 'id' => $id,
- 'course_id' => $course_id,
- 'title' => $lesson['title'],
- 'lesson' => $lesson,
- // needed for side panel and breadcrunbs
- 'categories' => $tree,
- 'breadcrumbs' => $breadcrumbs,
- 'course_path' => $course_path,
- // needed by footer
- 'entity' => Cache_service::pages_list()
- ]);
-
- } else { // user is not authorized
- Render::view('error/general', [
- 'title' => 'Δεν έχετε πρόσβαση',
- 'message' => 'Θα πρέπει να αγοράσετε το πακέτο πρόσβασης '
- . $pri_id
- .' για να δείτε το περιεχόμενο!
- <br><br>
- Αγόρασε τώρα το <button class="btn">πακέτο πρόσβασης '. $pri_id .'</button>'
- ]);
- }
-
- }
-
-
- ## PAGES
- ## -------------------------------------------------------------------------
-
-
- /** lesson
- *
- * check if user is authorized to view the content;
- * if so, prepare and render the lesson view
- *
- * @param $id : lesson id
- */
- public static function page($id)
- {
- $id = intval($id); // lesson id
-
- $pages = Cache_service::pages_list();
- $page = $pages[$id];
-
- // then Render
- // --- -- -- - - -
- Render::view('templates/page', [
- // main content
- 'id' => $id,
- 'page' => $page,
- // needed by footer
- 'entity' => $pages
- ]);
-
- }
-
-}
diff --git a/public/app/controllers/JsonToForm.php b/public/app/controllers/JsonToForm.php
index 1b05af7..5df650d 100644
--- a/public/app/controllers/JsonToForm.php
+++ b/public/app/controllers/JsonToForm.php
@@ -1,4 +1,5 @@
<?php
+namespace app\controllers;
class JsonToForm
{
@@ -141,14 +142,20 @@ class JsonToForm
return (mb_strlen($str) > $len) ? mb_substr($str, 0, $len-1) ."…" : $str;
}
-
- public static function make_a_form($form)
+ /** json_form
+ *
+ * construct a form (html, javasctipt)
+ * from a json designer
+ *
+ */
+ public static function json_form($formJson, $require_identity = [])
{
- $formJson = json_decode(json_encode($form));
+ // $formJson = json_decode(json_encode($form));
- $default_outer = $form->defaults->outer_class ?? '';
- $default_inner = $form->defaults->inner_class ?? '';
- $default_type = $form->defaults->type ?? 'text';
+ $default_outer = $formJson->defaults->outer_class ?? '';
+ $default_inner = $formJson->defaults->inner_class ?? '';
+ $default_type = $formJson->defaults->type ?? 'text';
+ $default_values = $formJson->defaults->values ?? ((object) ['nothing' => true]);
// TODO handle $form->defaults->source;
@@ -180,8 +187,15 @@ class JsonToForm
$initSelectsJS = ""; // js to initialize select fields (single or multiple)
+ $identity = ""; // construct required identity hidden fields
+ foreach ($require_identity as $group) {
+ $identity .= "
+ <input type='hidden' name='". $group['name']
+ ."' value='". $group['value'] ."'>";
+ }
- $html = "
+ // now constuct the form body
+ $html = "{$identity}
<div class='row'>
";
@@ -191,15 +205,22 @@ class JsonToForm
$type = $field->type ?? $default_type;
$class = $field->class ?? "";
$label = $field->label;
- $name = $field->name ?? "$field->label";
-
- // TODO: auto value
-
+ $name = $field->name ?? $field->label;
+
+ // handle value assignment
+ if (isset($field->value)) { // if value property is set
+ $set_value = true; // (flag: value seted)
+ $value = (($field->value == 'auto') && isset($default_values->$name))
+ ? $default_values->$name // set auto value
+ : $field->value; // or other set-value
+ } else {
+ $set_value = false;
+ }
+ // print_r([ $set_value, $name, ($default_values->$name ?? 'none') ]);
+
$appendKey = in_array('append-key', $attributes) ? true : false; // append key (for selects)
- $required = in_array('required', $attributes) ? 'required' : ''; // required
+ $required = in_array('required', $attributes) ? '' : ''; // required
$asterisk = in_array('required', $attributes) ? '*' : ''; // asterisk in label if required
-
-
$html .= "
<div class='form-group {$class}'>
@@ -220,6 +241,15 @@ class JsonToForm
var {$name} = $('#{$name}');
{$name}.select2({ width: '100%', placeholde: '{$label}' });";
+ if ($set_value) { // if default value is set
+ $initSelectsJS .= "
+ select2_set_multi_text( {$name} , {$value} );";
+
+ } else {
+ $initSelectsJS .= "
+ {$name}.val(null).trigger('change');";
+ }
+
// prepare check if empty field
$checkFilledJS .= "
if (getValues({$name}) =='') { empty += '{$label} {$asterisk}<br />'; }
@@ -234,8 +264,16 @@ class JsonToForm
// prepare initialization of select2 (single)
$initSelectsJS .= "
var {$name} = $('#{$name}');
- {$name}.select2({ });
- {$name}.val(null).trigger('change')";
+ {$name}.select2();";
+
+ if ($set_value) { // if default value is set
+ $initSelectsJS .= "
+ select2_set_text( {$name} , '{$value}' );";
+
+ } else {
+ $initSelectsJS .= "
+ {$name}.val(null).trigger('change');";
+ }
// prepare check if empty field
$checkFilledJS .= "
@@ -259,8 +297,10 @@ class JsonToForm
case 'text':
+ $def_value = ($set_value) ? "value='{$value}'" : "value=''";
+
$html .= "
- <input type='text' class='form-control form-control-sm' name='{$name}' {$required}>";
+ <input type='text' class='form-control form-control-sm' name='{$name}' $def_value {$required}>";
$checkFilledJS = "
if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}<br />'; }
@@ -271,6 +311,8 @@ class JsonToForm
case 'password':
+ $def_value = ($set_value) ? "value='{$value}'" : "value=''";
+
$html .= "
<input type='password' class='form-control form-control-sm' name='{$name}' {$required}>";
@@ -283,8 +325,10 @@ class JsonToForm
case 'integer':
+ $def_value = ($set_value) ? "value='{$value}'" : "value=''";
+
$html .= "
- <input type='number' class='form-control form-control-sm' name='{$name}' min='0' step='1' {$required}>";
+ <input type='number' class='form-control form-control-sm' name='{$name}' min='0' step='1' $def_value {$required}>";
$checkFilledJS .= "
if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}<br />'; }
@@ -295,8 +339,10 @@ class JsonToForm
case 'textarea':
+ $def_value = ($set_value) ? "{$value}" : "";
+
$html .= "
- <textarea class='form-control form-control-sm' name='{$name}' {$required}></textarea>";
+ <textarea class='form-control form-control-sm' name='{$name}' {$required}>{$def_value}</textarea>";
$checkFilledJS .= "
if ($('textarea[name={$name}]').val() =='') { empty += '{$label} {$asterisk}<br />'; }
@@ -319,8 +365,10 @@ class JsonToForm
case 'email':
+ $def_value = ($set_value) ? "value='{$value}'" : "value=''";
+
$html .= "
- <input type='email' class='form-control form-control-sm' name='{$name}' {$required}>";
+ <input type='email' class='form-control form-control-sm' name='{$name}' {$def_value} {$required}>";
$checkFilledJS .= "
if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}<br />'; }
@@ -332,7 +380,6 @@ class JsonToForm
default: // label, acts as common text
//$html .= "<label>{$label}</label";
-
}
diff --git a/public/app/controllers/Office.php b/public/app/controllers/Office.php
new file mode 100644
index 0000000..cfadde3
--- /dev/null
+++ b/public/app/controllers/Office.php
@@ -0,0 +1,424 @@
+<?php
+
+namespace app\controllers;
+
+use Registry;
+use Render;
+use app\controllers\Auth;
+use app\extends\App_manager;
+use app\models\Cms_model;
+use app\extends\Cache_service;
+
+/** Office class
+ *
+ * Manages all requests (front/back-office)
+ */
+class Office {
+
+ ## -------------------------------------------------------------------------
+ ##
+ ## SERVE METHODS (selects)
+ ##
+ ## -------------------------------------------------------------------------
+
+ ## PERMITION
+ ## -------------------------------------------------------------------------
+
+
+ /** is admin or permited
+ *
+ * shortcut method for checking access authorization
+ *
+ * returns true if user belogns to the admin group
+ * OR has the specified permition/privilege
+ *
+ * @param $privilege_id (int)
+ *
+ * NOTE:
+ * unlike the other authorization methods ...
+ * $privilege_id is NOT an array but a single privilege id
+ *
+ * @return true|false
+ */
+ private static function is_admin_or_permited( $privilege_id )
+ {
+ return (
+ Auth::in_admin_group()
+ || Auth::hasPermition([ $privilege_id ])
+ );
+ }
+
+
+
+ ## SERVE FILE
+ ## -------------------------------------------------------------------------
+
+
+ /** serve file by file_path
+ * (request is valid only for admin users)
+ *
+ * @param $file_path (string): relative file path
+ * GET @param type (string) : media-type of file
+ */
+ public static function serve_file($file_path)
+ {
+ $file = self::get_file_attributes($file_path);
+
+ // if user is authorized
+ if (self::is_admin_or_permited($file['privilege_id'])) {
+
+ $media_type = Registry::get('REQUEST')->GET['type']; // get media-type
+ $real_path = MEDIA_STORAGE_ROOT . $file_path; // construct real path
+
+ if (!file_exists($real_path)) {
+ Render::view('error/404');
+
+ } else {
+ Render::file($real_path, $media_type);
+ }
+
+ } else {
+ Render::view('error/404', [
+ 'error_code' => 403,
+ 'moto' => 'Forbidden',
+ 'message' => ''
+ ]);
+ }
+ }
+
+
+ /** get_file_attributes
+ *
+ * returns attributes of a file
+ * (medias are proxied for speed optimization)
+ *
+ * @param $path (string) : file path
+ * @return $file attributes --or-- false
+ */
+ private static function get_file_attributes($path)
+ {
+ $medias = Cache_service::files_attributes();
+
+ foreach($medias as $key => $medi) {
+
+ if ($medi['path'] == $path) {
+
+ return $medi;
+ }
+ }
+
+ return false;
+ }
+
+
+
+ ## PETITIONS
+ ## -------------------------------------------------------------------------
+ ## secretarial support / teachers' requests and applications
+
+
+
+ /** (any) petition
+ *
+ * check if user is authorized to view the content;
+ * if so, prepare and render the petition view
+ *
+ * @param $petition_type (string): [common|penalty]
+ */
+ public static function request_petition($petition_tag)
+ {
+ // get current user
+ $manager = new App_manager();
+ if (!$manager->hasUserToken()) { // if user is not connected
+ Render::view('error/404', [
+ 'error_code' => 403, // serve forbidden
+ 'moto' => 'Forbidden',
+ 'message' => 'Για να έχετε πρόσβαση, θα πρέπει πρώτα να συνδεθείτε'
+ ]);
+ die(); // then end;
+ }
+
+ $token = $manager->getUserToken(); // from token
+ $user = $token->getUser(); // create user
+ $id = $user->getID(); // keep id user
+
+ switch ($petition_tag) { // route to specific type of petition
+
+ case 'common':
+ self::render_common_petition(['user' => $user]);
+ break;
+
+ case 'penalty':
+ self::render_penalty_form(['user' => $user]);
+ break;
+
+ default: // if not a known petition type
+ Render::view('error/404', [ // then serve not-found
+ 'message' => 'Δεν βρέθηκε το είδος της αίτησης ή του εγγράφου που ζητήσατε.'
+ ]);
+ }
+ }
+
+
+ private static function render_penalty_form($opts)
+ {
+ $user_id = $opts['user']->getID();
+
+ $form_setup = json_decode(json_encode(PENALTY_FORM, JSON_UNESCAPED_UNICODE));
+
+ // get all teachers
+ $teachers_array = Registry::use('database')->runQuery(
+ "SELECT concat(last_name, ' ', first_name) as TeacherName
+ FROM user ORDER BY TeacherName", []
+ );
+ $teachers = []; // constuct teacher names as a simple array
+ foreach($teachers_array as $key => $person) {
+ $teachers[] = $person['TeacherName'];
+ }
+ // print_r( $teachers); die();
+
+ // get $key of rapporteur, president and members inside the form_setup->form array
+ for($i=0; $i < sizeof($form_setup->form) ; $i++) {
+ if (isset($form_setup->form[$i]->name)) {
+ if ($form_setup->form[$i]->name == 'rapporteur') { $keyRapporteur = $i; }
+ if ($form_setup->form[$i]->name == 'president') { $keyPresident = $i; }
+ if ($form_setup->form[$i]->name == 'members') { $keyMembers = $i; }
+ }
+ }
+
+ // set option sources for rapporteur, president and members
+ $form_setup->form[$keyRapporteur]->options = $teachers;
+ $form_setup->form[$keyPresident]->options = $teachers;
+ $form_setup->form[$keyMembers]->options = $teachers;
+
+ // get Form's HTML and Jsvascript
+ $form = JsonToForm::json_form($form_setup, [
+ ['name' => 'id', 'value' => $user_id] // pass user identity
+ ]);
+
+ Render::view('templates/penalty', ['form' => $form]);
+
+ }
+
+
+
+ ## -------------------------------------------------------------------------
+ ##
+ ## ADMIN METHODS (insert, updated etc.)
+ ##
+ ## -------------------------------------------------------------------------
+
+
+ /** files
+ * echo all files
+ *
+ * @return (array)
+ */
+ public static function files()
+ {
+ return Cache_service::files_attributes();
+ }
+
+
+ /** upload_file
+ * upload the file to the file system
+ *
+ * the method reads the POST and FILES array
+ * to retrieve all needed parametres
+ *
+ * FILES @param file
+ * POST @param folder : petition's ID or somthing random
+ * SESSION @param user_id
+ */
+ public static function upload_file()
+ {
+ $request = Registry::get('REQUEST');
+
+ $uploaded = self::upload_to_fs(); // upload file to file-system
+
+ if ($uploaded['success']) {
+
+ $media_id = self::define_media([ // define media in database; get id
+ 'title' => $request->POST['title'],
+ 'type' => $uploaded['type'],
+ 'path' => $uploaded['path']
+ ]);
+
+ Render::json([ // render results as json
+ 'success' => true,
+ 'id' => $media_id,
+ 'title' => $request->POST['title'],
+ 'path' => $uploaded['path'],
+ 'type' => $uploaded['type']
+ ]);
+
+ } else {
+ Render::json(['success' => false ]);
+ }
+ }
+
+
+ /** upload to fs
+ * upload file to File-System
+ *
+ * POST @param folder
+ * FILES @param file
+ */
+ private static function upload_to_fs()
+ {
+ $post = Registry::get('REQUEST')->POST;
+ $files = Registry::get('REQUEST')->FILES;
+
+
+ // Checks before uploading the file
+ ////////////////////////////////////////////////////////////////////////
+
+ // ** 1: file is upladed to temporary folder ---------------------------
+ if (! is_uploaded_file($files['file']['tmp_name'])) {
+ return ['success' => false]; // bye!
+ }
+
+ // ** 2: File belongs to the allowed MIME types ------------------------
+ $allowed_file_types = [
+ // pdf
+ 'application/pdf',
+ // images
+ 'image/png', 'image/jpeg',
+ // word
+ 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ // excel
+ 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ // rar
+ 'application/vnd.rar', 'application/x-rar-compressed', 'application/octet-stream',
+ // zip
+ 'application/zip', 'application/x-zip-compressed', 'multipart/x-zip'
+ // 'application/octet-stream' refers to zip; also to rar (no-need to re-include)
+ ];
+ // Recomended MIME type checking via mime_content_type():
+ $mime_type = mime_content_type($files['file']['tmp_name']);
+ if (! in_array($mime_type, $allowed_file_types)) { // File type NOT allowed ...
+ return ['success' => false]; // bye!
+ }
+
+ $file_name = $files['file']['name'];
+ $file_type = $files['file']['type']; // do not take it for granted
+ $file_size = $files['file']['size'];
+ $file_tmp = $files['file']['tmp_name'];
+
+ $bare_name = pathinfo($file_name, PATHINFO_FILENAME);
+ $file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
+
+
+ // ** 3: filename or size checks may be added --------------------------
+ if ($file_name == "") {
+ return ['success' => false]; // bye!
+ }
+
+
+ // READY to finaly save/upload the file to CDN /////////////////////////
+
+ $folder = MEDIA_STORAGE_ROOT . $post['folder'];
+ if (!file_exists($folder)) { // create folder if not exists
+ mkdir($folder, 0757, true);
+ }
+
+ // print_r([
+ // 'dir' => $folder,
+ // 'file' => $bare_name,
+ // 'ext' => $file_ext,
+ // 'type' => $file_type
+ // ]); die();
+
+ $relative_filename = $post['folder']
+ .'/'
+ . strtolower(self::clear_file_name($bare_name) .'.'. $file_ext);
+ $store_filename = MEDIA_STORAGE_ROOT . $relative_filename;
+
+ if (move_uploaded_file($files["file"]["tmp_name"], $store_filename)) {
+ return [
+ 'success' => true,
+ 'path' => $relative_filename,
+ 'type' => $mime_type
+ ];
+
+ } else { return ['success' => false]; }
+
+ }
+
+
+ /** clear_file_name
+ * replace greek characters and strip symbols
+ */
+ private static function clear_file_name($str)
+ {
+ $el = mb_split( "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωάέήίόύώϊϋς ", "");
+ $en = str_split("ABGDEZHUIKLMNJOPRSTYFXCVabgdezhuiklmnjoprstyfxcvaehioyviys-");
+ $strip = str_split("!@#$%^&*()+~`[]{};'/<>?=\"");
+
+ return str_replace($strip, '', str_replace($el, $en, $str));
+ }
+
+
+ /** define_media
+ *
+ * create a record in media table
+ *
+ * @param $data (array): [title => , path => , type => mime-type]
+ * @return id (int): id of created media record
+ */
+ private static function define_media($data)
+ {
+ $request = Registry::get('REQUEST');
+
+ $media_id = Registry::use('database')->query(
+ "INSERT INTO media (label, `type`, `path`)
+ VALUES (:label, :mimetype, :filepath)",
+ [
+ 'label' => $data['title'],
+ 'mimetype' => $data['type'],
+ 'filepath' => $data['path']
+ ]
+ )->lastInsertID();
+ return $media_id;
+ }
+
+
+ /** create media for petition
+ *
+ * links petition to each media-file of the media `id`s array
+ *
+ * @param $media (array): a list of media-file `id`s
+ * @param $petition_id (int)
+ */
+ private static function create_medias_for_petition($medias, $petition_id)
+ {
+ foreach($medias as $key => $medi) {
+ self::link_media_to_petition($medi, $petition_id); // link to petition
+ }
+ return true;
+ }
+
+ /** link one media-file to a specific post
+ *
+ * NOTE:
+ * the method does not check if media is linked already
+ * so be sure that the pair of (media_id,post_id) not exist
+ *
+ * @param $media_id (int)
+ * @param $petition_id (int)
+ */
+ private static function link_media_to_petition( $media_id, $petition_id )
+ {
+ Registry::use('database')->runQuery(
+ "INSERT INTO petition_media (petition_id, media_id)
+ VALUES (:petition, :media)",
+ [
+ 'petition' => $petition_id,
+ 'media' => $media_id,
+ ]
+ );
+ return true;
+ }
+
+
+}