diff options
| author | George Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2023-05-04 03:02:01 +0300 |
|---|---|---|
| committer | George Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2023-05-04 03:02:01 +0300 |
| commit | 63f714d5a78b765c117ebf6bbdfdbd748dd45644 (patch) | |
| tree | 87a4db40e1ff699222ccfdf699a3904d1c665bfc /public/app | |
| parent | 931a93cd7bae092e2752064568cebe407d2bf46e (diff) | |
| download | gyraf1gov-63f714d5a78b765c117ebf6bbdfdbd748dd45644.tar.gz gyraf1gov-63f714d5a78b765c117ebf6bbdfdbd748dd45644.tar.bz2 gyraf1gov-63f714d5a78b765c117ebf6bbdfdbd748dd45644.zip | |
authentication; invitation; activation; base form setup
Diffstat (limited to 'public/app')
| -rw-r--r-- | public/app/config/app_constants.php | 124 | ||||
| -rw-r--r-- | public/app/controllers/Auth.php | 280 | ||||
| -rw-r--r-- | public/app/controllers/Cms.php | 259 | ||||
| -rw-r--r-- | public/app/controllers/JsonToForm.php | 89 | ||||
| -rw-r--r-- | public/app/controllers/Office.php | 424 | ||||
| -rw-r--r-- | public/app/extends/App_manager.php | 4 | ||||
| -rw-r--r-- | public/app/extends/App_user.php | 63 | ||||
| -rw-r--r-- | public/app/extends/Cache_service.php | 19 | ||||
| -rw-r--r-- | public/app/models/Access_model.php | 57 | ||||
| -rw-r--r-- | public/app/models/Office_model.php (renamed from public/app/models/Cms_model.php) | 0 | ||||
| -rw-r--r-- | public/app/models/_info.md | 21 | ||||
| -rw-r--r-- | public/app/routes/backend.php | 11 | ||||
| -rw-r--r-- | public/app/routes/frontend.php | 15 | ||||
| -rw-r--r-- | public/app/routes/user.php | 13 | ||||
| -rw-r--r-- | public/app/views/error/404.php | 12 | ||||
| -rw-r--r-- | public/app/views/templates/penalty.php | 12 | ||||
| -rw-r--r-- | public/app/views/user/invitation.php (renamed from public/app/views/user/registration.php) | 96 | ||||
| -rw-r--r-- | public/app/views/welcome.php | 15 |
18 files changed, 858 insertions, 656 deletions
diff --git a/public/app/config/app_constants.php b/public/app/config/app_constants.php index 9dff566..262a727 100644 --- a/public/app/config/app_constants.php +++ b/public/app/config/app_constants.php @@ -25,6 +25,12 @@ if (file_exists("../core/auth/.env")) { define('SITE_TITLE', 'Classroom'); define('SITE_URL', 'http://localhost'); +// Session and cookie names +// --- -- -- - - - +define('SESSION_NAME', 'offticket'); // cookie for session (office ticket) +define('CONNECTION_COOKIE', 'con'); // cookie for connection +define('MAX_SESSION_LIFE', 2*60*60); // maximum session lifetime (2 hours) + // email setup // --- -- -- - - - // SMTP @@ -144,82 +150,110 @@ define('ACCOUNT_ACTIVATED_TITLE', 'Ο λογαριασμός σας έχει ε define('ACCOUNT_ACTIVATED_MESSAGE', 'Τώρα μπορείτε να <a href="/login">συνδεθείτε στο σύστημα</a>.'); define('NOT_VALID_ACTIVATION_TITLE', 'Σφάλμα!'); +define('NOT_VALID_ACTIVATION_MESSAGE', 'Ο λογαριασμός δεν έχει ενεργοποιηθεί. + Ξαναδοκιμάστε αργότερα κι αν το σφάλμα επιμείνει, επικοινωνήστε με την υπεύθυνη του προγράμμαρος.'); +// forms +// --- -- -- - - - - +// registration/activation form (from invitation) +// --- define('REGISTRATION_FORM', [ 'defaults' => [ 'outer_class' => 'col-12', 'inner_class' => 'form-control', - 'type' => 'text' + 'type' => 'text', + 'source' => '\app\controllers\User::current' ], 'form' => [ [ 'name' => 'first_name', 'label' => 'Όνομα', + 'value' => 'auto', 'attributes' => ['required'] ], [ 'name' => 'last_name', 'label' => 'Επίθετο', + 'value' => 'auto', 'attributes' => ['required'] ], [ 'name' => 'email', 'label' => 'e-mail', 'type' => 'email', + 'value' => 'auto', 'attributes' => ['required'] ], [ 'name' => 'father_name', 'label' => 'Πατρώνυμο', + 'value' => 'auto', 'attributes' => ['required'] ], [ 'name' => 'registration_number', 'label' => 'Αριθμός μητρώου', 'class' => 'col-8', + 'value' => 'auto', 'attributes' => ['required'] ], [ 'name' => 'sector', 'label' => 'Κλάδος / Ειδικότητα', + 'value' => 'auto', 'type' => 'select', - // 'source' => 'sectors', 'attributes' => ['required'], 'options' => [ - 'Π01.00 Θεολόγοι', - 'Π02.00 Φιλόλογοι', - 'Π04.01 Φυσικοί', - 'Π04.02 Χημικοί' + 'ΠΕ01 ΘΕΟΛΟΓΟΙ', + 'ΠΕ02 ΦΙΛΟΛΟΓΟΙ', + 'ΠΕ02.50 ΦΙΛΟΛΟΓΟΙ ΕΙΔΙΚΗΣ ΑΓΩΓΗΣ', + 'ΠΕ03 ΜΑΘΗΜΑΤΙΚΟΙ', + 'ΠΕ03.50 ΜΑΘΗΜΑΤΙΚΟΙ ΕΙΔΙΚΗΣ ΑΓΩΓΗΣ', + 'ΠΕ04.01 ΦΥΣΙΚΟΙ', + 'ΠΕ04.01.50 ΦΥΣΙΚΟΙ ΕΙΔΙΚΗΣ ΑΓΩΓΗΣ', + 'ΠΕ04.02 ΧΗΜΙΚΟΙ', + 'ΠΕ04.04 ΒΙΟΛΟΓΟΙ', + 'ΠΕ05 ΓΑΛΛΙΚΗΣ ΦΙΛΟΛΟΓΙΑΣ', + 'ΠΕ06 ΑΓΓΛΙΚΗΣ ΦΙΛΟΛΟΓΙΑΣ', + 'ΠΕ07 ΓΕΡΜΑΝΙΚΗΣ ΦΙΛΟΛΟΓΙΑΣ', + 'ΠΕ08 ΚΑΛΛΙΤΕΧΝΙΚΩΝ', + 'ΠΕ11 ΦΥΣΙΚΗΣ ΑΓΩΓΗΣ', + 'ΠΕ23-ΣΔΕΥ ΨΥΧΟΛΟΓΟΙ', + 'ΠΕ30-ΣΔΕΥ ΚΟΙΝΩΝΙΚΟΙ ΛΕΙΤΟΥΡΓΟΙ', + 'ΠΕ78 ΚΟΙΝΩΝΙΚΩΝ ΕΠΙΣΤΗΜΩΝ', + 'ΠΕ79.01 ΜΟΥΣΙΚΗΣ ΕΠΙΣΤΗΜΗΣ', + 'ΠΕ80 ΟΙΚΟΝΟΜΙΑΣ', + 'ΠΕ81 ΠΟΛ.ΜΗΧΑΝΙΚΩΝ-ΑΡΧΙΤΕΚΤΟΝΩΝ', + 'ΠΕ82 ΜΗΧΑΝΟΛΟΓΩΝ', + 'ΠΕ86 ΠΛΗΡΟΦΟΡΙΚΗΣ', + 'ΠΕ88.01 ΓΕΩΠΟΝΟΙ' ] ], [ 'name' => 'belonging_school', 'label' => 'Σχολείο τοποθέτησης', + 'value' => 'auto', 'attributes' => ['required'] ], - [ - 'name' => 'working_school', - 'label' => 'Σχολείο εργασίας', - 'attributes' => ['required'] - ], + // [ // working school = (obviously) is the current school + // 'name' => 'working_school', + // 'label' => 'Σχολείο εργασίας', + // 'attributes' => ['required'] + // ], [ 'name' => 'position', 'label' => 'Θέση', 'type' => 'select', + 'value' => 'auto', 'attributes' => ['required'], - 'options' => [ - 'Διευθυν-τής/τρια', - 'Υποδιευθυν-τής/τρια', - 'Μόνιμ-ος/η Καθηγη-τής/τρια', - 'Αναπληρω-τής/τρια', - ] + 'options' => [] ], [ 'name' => 'phone', 'label' => 'Τηλέφωνο', 'class' => 'col-8', + 'value' => 'auto', 'attributes' => ['required'] ], [ @@ -239,7 +273,8 @@ define('REGISTRATION_FORM', [ ] ]); - +// common requesy form (for any application) +// --- define('COMMON_REQUEST_FORM', [ 'defaults' => [ 'outer_class' => 'col-12', @@ -317,6 +352,8 @@ define('COMMON_REQUEST_FORM', [ ] ]); +// penalty form +// --- define('PENALTY_FORM', [ 'defaults' => [ @@ -382,6 +419,7 @@ define('PENALTY_FORM', [ [ 'name' => 'rapporteur', 'label' => 'εισηγητής', + 'type' => 'select', 'source' => '\app\extends\Cache_service::all_users', 'attributes' => ['required'] ], @@ -426,7 +464,7 @@ define('PENALTY_FORM', [ [ 'name' => 'president', 'label' => 'Πρόεδρος συνεδρίασης', - 'type' => 'text', + 'type' => 'select', 'source' => '\app\extends\Cache_service::all_users', 'attributes' => ['required'] ], @@ -435,51 +473,7 @@ define('PENALTY_FORM', [ 'label' => 'Μέλη', 'type' => 'select', 'attributes' => ['required', 'multiple'], - 'source' => '\app\extends\Cache_service::all_users', - 'options' => [ - 'Μαρία Χαλκιαδάκη', - 'Σπαγκοβαγγελοδημήτρης Νικόλαος', - 'Χατζηχριστοδούλου Παναγιώτης', - 'Μαρία Χαλκιά', - 'Σπανοβαγγελοδημήτρης Νικόλαος', - 'Χριστοδούλου Παναγιώτης', - 'Μαρίκα Χαλκιαδάκη', - 'Σπανακοβαγγελοδημήτρης Νικόλαος', - 'Χατζηχριστοδούλου Χριστόδουλος', - 'Αννέτα Καββαδία', - 'Γιώργος Καΐσας', - 'Διονύσης - Χαράλαμπος Καλαματιανός', - 'Ηλίας Καματερός', - 'Μαρία Κανελλοπούλου', - 'Ιωάννης Καραγιάννης', - 'Χρήστος Καραγιαννίδης', - 'Ευαγγελία Καρακώστα', - 'Απόστολος Καραναστάσης', - 'Ευφροσύνη Καρασαρλίδου', - 'Νίνα Κασιμάτη', - 'Αστέριος Καστόρης', - 'Βασιλική Κατριβάνου', - 'Γιώργος Κατρούγκαλος', - 'Χρυσούλα Κατσαβριά-Σιωροπούλου', - 'Μάριος Κάτσης', - 'Χαρά Καφαντάρη', - 'Σίμος Α. Κεδίκογλου', - 'Παναγιώτα Κοζομπόλη-Αμανατίδη', - 'Βασίλης Κόκκαλης', - 'Σταύρος Κοντονής', - 'Περικλής Κοροβέσης', - 'Νίκος Κοτζιάς', - 'Φώτης Κουβέλης', - 'Τάσος Κουράκης', - 'Παναγιώτης Κουρουμπλής', - 'Μιχαήλ Κριτσωτάκης', - 'Βασίλης Κυριακάκης', - 'Αγλαΐα Κυρίτση', - 'Γιώργος Κυρίτσης', - 'Πέτρος Κωνσταντινέας', - 'Ζωή Κωνσταντοπούλου', - 'Ηλίας Κωστοπαναγιώτου' - ] + 'source' => '\app\extends\Cache_service::all_users' ] ] ]); 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; + } + + +} diff --git a/public/app/extends/App_manager.php b/public/app/extends/App_manager.php index 8e6ce95..b003015 100644 --- a/public/app/extends/App_manager.php +++ b/public/app/extends/App_manager.php @@ -53,7 +53,9 @@ class App_manager extends UserManager } - + /** ?? + * + */ public function login_user() { diff --git a/public/app/extends/App_user.php b/public/app/extends/App_user.php index 9aed489..6e93969 100644 --- a/public/app/extends/App_user.php +++ b/public/app/extends/App_user.php @@ -12,14 +12,6 @@ use Registry; * this way it specializes the UserManagement * according to this app's special rules * - * Add privileges concept - * --- - * A Class_user has privileges (which are deferent than Roles) - * In fact, privileges extend the authorization requirements for users - * - * Authorized content is marked with some 'minimum Privilege' - * So the content is available to the READER(s) that have certain Privileges - * */ class App_user extends User { @@ -29,18 +21,20 @@ class App_user extends User */ private $id; - /** user privileges - * @var array + /** sex (gender) + * @var int (1 = male, 2 = female ) */ - private $privileges = []; + private $sex; /** user name - * @var string + * @var string : first_name +' '+ last_name */ private $name; + + /** SETTERS AND GETTERS - * for id, name, privileges attributes + * for id, name, attributes * ------------------------------------------------------------------------- */ @@ -68,54 +62,55 @@ class App_user extends User } - // name + // sex // --- -- -- - - - - /** getName + /** getSex() * @return int */ - public function getName(): string + public function getSex(): int { - return $this->name; + return $this->sex; } - /** setName() + + /** setSex() * - * @param string : user's full name + * @param int : sex (id) * * @return User */ - public function setName(string $name): self + public function setSex(int $sex): self { - $this->name = $name; + $this->sex = $sex; return $this; } - - // privileges + + + // name // --- -- -- - - - - /** getPrivileges - * - * @return privileges (array) + /** getName + * @return string */ - public function getPrivileges(): array + public function getName(): string { - return $this->privileges; + return $this->name; } - - /** setPrivileges() + /** setFirstName() * - * @param array $privileges + * @param string : user's full name * * @return User */ - public function setPrivileges(array $privileges): self + public function setName(string $name): self { - $this->privileges = $privileges; + $this->name = $name; return $this; } - + + }
\ No newline at end of file diff --git a/public/app/extends/Cache_service.php b/public/app/extends/Cache_service.php index c435b75..05fd39e 100644 --- a/public/app/extends/Cache_service.php +++ b/public/app/extends/Cache_service.php @@ -36,25 +36,6 @@ class Cache_service } - public static function privileges_hierarchy( $options = 0 ) - { - return proxy( - [\app\models\Access_model::class, 'privileges'], - [], CACHE_ROOT_TTL, - $options - ); - } - - public static function pages_list( $options = 0 ) - { - return proxy( - [\app\models\Cms_model::class, 'pages'], - [], CACHE_ROOT_TTL, - $options - ); - } - - /** entity * * create and retrieve a cached array of some entity diff --git a/public/app/models/Access_model.php b/public/app/models/Access_model.php index 8d446dc..8a2e5ce 100644 --- a/public/app/models/Access_model.php +++ b/public/app/models/Access_model.php @@ -3,6 +3,7 @@ namespace app\models; use \Registry; +use app\extends\App_manager; use app\models\History_model; class Access_model @@ -148,36 +149,52 @@ class Access_model } - /** activate + /** activate_set_password * - * check if activation code is valid; - * if valid, set account active; + * activate user and set password * * @param $ticket (hex/MD5): activation code; * */ - public static function activate($ticket) + public static function activate_set_password($post, $password) { - $user = Registry::use('database')->query( - "SELECT * FROM user WHERE activation = :ticket", - [ 'ticket' => $ticket ] - )->getFirst(); - - // if no user with this activation code, return false - if ($user === false) return false; - - // remove activation code from user record - Registry::use('database')->runQuery( + // Update and set activate = true + $rowCount = Registry::use('database')->query( "UPDATE user - SET active = 1, `activation` = NULL - WHERE activation = :ticket", - [ 'ticket' => $ticket ] - ); + SET first_name = :first_name, + last_name = :last_name, + email = :email, + father_name = :father_name, + registration_number = :registration_number, + sector = :sector, + belonging_school = :belonging_school, + position = :position, + phone = :phone, + `password` = :password, + invitation = NULL, + active = :active + WHERE id = :id AND invitation = :invitation", + [ + ':first_name' => $post['first_name'], + ':last_name' => $post['last_name'], + ':email' => $post['email'], + ':father_name' => $post['father_name'], + ':registration_number' => $post['registration_number'], + ':sector' => $post['sector'], + ':belonging_school' => $post['belonging_school'], + ':position' => $post['position'], + ':phone' => $post['phone'], + ':password' => $password, + ':active' => 1, + ':id' => $post['id'], + ':invitation' => $post['invitation'] + ] + )->rowCount(); // update history - History_model::trackUserAccess($user['id'], TRACK_ACCOUNT, 'User Account Activated'); + History_model::trackUserAccess($post['id'], TRACK_ACCOUNT, 'User Account Activated'); - return true; + return $rowCount; } diff --git a/public/app/models/Cms_model.php b/public/app/models/Office_model.php index fad11b8..fad11b8 100644 --- a/public/app/models/Cms_model.php +++ b/public/app/models/Office_model.php diff --git a/public/app/models/_info.md b/public/app/models/_info.md index 82143bf..ac6d334 100644 --- a/public/app/models/_info.md +++ b/public/app/models/_info.md @@ -150,3 +150,24 @@ $myobject = new myclass(); call_user_func(array($myobject, 'say_hello')); ?> + + + + +# APPlication + +\ controllers + [ ] App + [ ] Auth + +\ extends + [ ] Cache_service + [*] App_manager + [*] App_user + [ ] SendMail_service + [ ] Form_builder + + +\ models + [ ] Access_model + [ ] History_model
\ No newline at end of file diff --git a/public/app/routes/backend.php b/public/app/routes/backend.php index 1290f8a..6fbc157 100644 --- a/public/app/routes/backend.php +++ b/public/app/routes/backend.php @@ -1,9 +1,9 @@ <?php -use app\controllers\Auth; -use app\controllers\CmsAdmin; -use app\models\admin\Privilege_model; -use app\extends\Cache_service; +//// use app\controllers\Auth; +//// use app\controllers\CmsAdmin; +//// use app\models\admin\Privilege_model; +//// use app\extends\Cache_service; /** admin pages @@ -11,7 +11,7 @@ use app\extends\Cache_service; * NOTE: * All adminitration routes MUST INCLUDE an Auth::allowRoles() check */ - +/* // admin panel //////////////////////////////////////////////////////////////////////////////// @@ -167,3 +167,4 @@ Route::add('/admin/api/pages', function () { // ajax: get all pages CmsAdmin::all_pages(); }); +*/
\ No newline at end of file diff --git a/public/app/routes/frontend.php b/public/app/routes/frontend.php index 2defce5..b0e064b 100644 --- a/public/app/routes/frontend.php +++ b/public/app/routes/frontend.php @@ -1,8 +1,8 @@ <?php use app\controllers\Auth; -use app\controllers\Classroom_user; -use app\controllers\Cms; +use app\controllers\App_user; +use app\controllers\Office; use app\extends\Cache_service; @@ -10,9 +10,16 @@ use app\extends\Cache_service; //////////////////////////////////////////////////////////////////////////////// // Route::add('/', function() { Render::view('welcome'); }); -Route::add('/', function() { Render::view('user/registration'); }); +Route::add('/', function() { Render::view('user/login'); }); -Route::add('/penalty', function() { Render::view('templates/penalty'); }); + +Route::add('/invitation/([0-9]*)', function($id) { + Auth::invitation($id); +}); + +Route::add('/petition/([0-9a-z\-_]*)', function($tag) { + Office::request_petition($tag); +}); // Error pages //////////////////////////////////////////////////////////////////////////////// diff --git a/public/app/routes/user.php b/public/app/routes/user.php index 146b212..a2d48d6 100644 --- a/public/app/routes/user.php +++ b/public/app/routes/user.php @@ -13,29 +13,28 @@ use app\controllers\Classroom_user; // request login ... -> then sends to POST:/account/check-login Route::add('/login', function() { Render::view('user/login'); }); -// request registration ... -> then sends to POST:/account/register -Route::add('/registration', function() { Render::view('user/registration'); }); - // request logout Route::add('/logout', function() { Auth::logout(); header('Location: /'); die(); }); -// request activation -Route::add('/account/activate', function() { Auth::activate(); } ); +// request activation (from invitation page; POST:form is sent) +Route::add('/account/activate', function() { Auth::activate(); }, 'post'); // request password reset Route::add('/account/reset_password', function() { Auth::reset_password(); } ); -// invite +// invite some users Route::add('/invite', function() { Auth::allowRoles([1, 2, 3]); Render::view('admin/invite'); }); - +Route::add('/panel', function() { + Render::json(['connected' => Auth::is_connected()]); +}); // Replies to common requests (POST method) // --- -- -- - - - diff --git a/public/app/views/error/404.php b/public/app/views/error/404.php index a085830..41f17da 100644 --- a/public/app/views/error/404.php +++ b/public/app/views/error/404.php @@ -7,7 +7,6 @@ * * optional @var $error_code (int) : error code * optional @var $moto (string) : super-mini description text - * optional @var $message (string) * */ @@ -15,14 +14,14 @@ $error_code = 404; // set default (404) } - http_response_code(403); + http_response_code($error_code); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> - <title>404: Not Found</title> + <title><?=$error_code?> : <?= $moto ?? 'Not found' ?></title> <style> html,body{ @@ -52,13 +51,10 @@ <body> <div class='container'> <div class='content'> + <h3><?=$error_code?></h3> <?= $moto ?? 'Not found' ?><br /> - <!-- - — - <br /> - <span><?= $message ?? "and I still haven't found what I'm looking for." ?></span> - --> + </div> </div> </body> diff --git a/public/app/views/templates/penalty.php b/public/app/views/templates/penalty.php index 6a8f563..bbd7b4a 100644 --- a/public/app/views/templates/penalty.php +++ b/public/app/views/templates/penalty.php @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="utf-8"> - <title><?=SITE_TITLE?> - Εγγραφή</title> + <title><?=SITE_TITLE?> - Πρακτικό Πειθαρχικής Υπόθεσης</title> <?php // header includes //////////////////////////////////////////////////////////////////////// @@ -56,14 +56,8 @@ <div class='content-form'> <form method="post"> <div> - <p>1o Γυμνάσιο Ραφήνας /<br /> - Πλατφόρμα ηλεκτρονικών αιτήσεων και δημιουργίας διαδικαστικών εγγράφων</p> - <h2>Πρόσκληση #</h2> - - <?php - $form = JsonToForm::make_a_form(PENALTY_FORM); - ?> + <h2>Πρακτικό Πειθαρχικής Υπόθεσης</h2> <?=$form['html']?> @@ -122,6 +116,8 @@ <?=$form['init_js']?> + + <?=$form['values_js']?> </script> </html> diff --git a/public/app/views/user/registration.php b/public/app/views/user/invitation.php index 9eb0ea3..eb34bc4 100644 --- a/public/app/views/user/registration.php +++ b/public/app/views/user/invitation.php @@ -43,7 +43,7 @@ label { font-size: 14px; } </style> </head> -<body class="classroom"> +<body class="office"> <div class='container'> <div class="content"> <div class="info"> @@ -58,10 +58,6 @@ <h2>Πρόσκληση #</h2> - <?php - $form = JsonToForm::make_a_form(REGISTRATION_FORM); - ?> - <?=$form['html']?> <br /> @@ -80,42 +76,104 @@ </body> <script> +var values = {}; +var empty = ''; + +$(document).ready(function() { + + /** select2_set_text + * select an (select2-)option by text + * + * @param control = jquery selector, + * @param t (string) = text of option + */ + function select2_set_text(control, t) { /* define function */ + opts = control.select2()[0].options; + var id; + for(i=0; i<opts.length; i++) { if (opts[i].text == t) id = i; } + control.val(id).trigger('change'); + } + + /** get_id_of_text + * get id (=value) of an option with `t` text + * + * @param control = jquery selector, + * @param t (string) = text of option + */ + function get_id_of_text( control , t) { /* define id from text */ + opts = control.select2()[0].options; + var id = false; + for(i=0; i<opts.length; i++) { if (opts[i].text == t) id = i; } + return id; + } + + /** select2_set_multi_text + * select several (select2-)options by text + * + * @param control = jquery selector, + * #param t_list (string) = list of selected texts + */ + function select2_set_multi_text(control, t_list) { /* define function */ + var ids = []; + t_list.forEach (t => { let id = get_id_of_text(control, t); + if (id !== false) ids.push(id); + }) + control.val(ids).change(); + } + + + <?=$form['init_js']?> + + <?=$form['values_js']?> + // When form is submited // ------------------------------------------------------------------------- - $('.content-form form').submit( event => { + $('form').submit( event => { event.preventDefault(); - if ($('input[name=password]').val() != $('input[name=password2]').val()) { - alert('Τα δυο passrods δεν ταιριάζουν!'); + if ($('input[name=password]').val() != $('input[name=confirm_password]').val()) { + alert('Τα δυο κωδικοί πρόσβασης δεν ταιριάζουν!'); + + } else if ($('input[name=password]').val() == "") { + alert('Ο κωδικός πρόσβασης δεν μπορεί να είναι κενός') - } else { + } else if ( ($('input[name=password]').val() == '0') + || ($('input[name=password]').val() =='') ) { + alert('Παρκαλώ συμπληρώστε ένα τηλέφωνο επικοινωνίας') + } else { // prepare data to POST var data = { + // identification fields + id: $('input[name=id]').val(), + invitation: $('input[name=invitation]').val(), + // data fields first_name: $('input[name=first_name]').val(), last_name: $('input[name=last_name]').val(), + father_name: $('input[name=father_name]').val(), email: $('input[name=email]').val(), registration_number: $('input[name=registration_number]').val(), - sector: $('input[name=sector]').val(), + sector: $('select[name=sector]').select2('data')[0].text, belonging_school: $('input[name=belonging_school]').val(), - working_shcool: $('input[name=working_shcool]').val(), - position_type_id: $('input[name=position_type_id]').val(), + position: $('select[name=position]').select2('data')[0].text, phone: $('input[name=phone]').val(), + // access verification password: $('input[name=password]').val() }; - - // select action url (add or update) - var request = '/account/register'; + // console.log('post:', data); + + var request = '/account/activate'; // set action url // send POST request $.post(request, data) .done(function( data ) { - $('.classroom .content-form').html(data.message) + $('.office .content-form').html(data.message) }); - } - + } }); -</script> + +}); +</script> </html> diff --git a/public/app/views/welcome.php b/public/app/views/welcome.php index e97f748..fd3f703 100644 --- a/public/app/views/welcome.php +++ b/public/app/views/welcome.php @@ -26,15 +26,14 @@ select option { font-size: .87rem; } </head> <body class='classroom'> <div class="container" style="max-width: 640px;"> - <div class="row"> + <div class="row"> - <?php - $form = JsonToForm::make_a_form(REGISTRATION_FORM); - ?> +<?php + $form = JsonToForm::make_a_form(REGISTRATION_FORM); +?> +<?=$form['html']?> - <?=$form['html']?> - - </div> + </div> </div> @@ -196,6 +195,8 @@ $('.select-field').select2({ width: '100%' }); // --------------------------------------------------------------------------- <?=$form['init_js']?> +<?=$form['values_js']?> + // 04. FORM-LOGIC // --------------------------------------------------------------------------- |
