diff --git a/app/Controllers/Admin.php b/app/Controllers/Admin.php new file mode 100644 index 0000000..6b8b7ae --- /dev/null +++ b/app/Controllers/Admin.php @@ -0,0 +1,170 @@ +getQueryParams(); + + $users = $this->loadUsers(); + + $users->setPath($this->container->router->pathFor('adminUsersManagement')); + + $this->render($this->container->project->pathFor('adminUsersManagement.html.twig'), [ + 'class' => 'admin', + 'showmodal' => isset($get['showmodal']), + 'users' => $users, + 'uuid' => isset($get['uuid']) ? $get['uuid'] : '', + 'user_session' => $_SESSION['user'], + 'actions' => $this->getUsersActions(), + 'pagination' => $_SESSION['users_management']['pagination'], + 'orderby' => $_SESSION['users_management']['orderby'], + 'sort' => $_SESSION['users_management']['sort'], + 'customFilter' => $_SESSION['users_management']['customFilter'], + 'search' => $_SESSION['users_management']['search'], + 'action_code' => $_SESSION['users_management']['action_code'], + 'search_on' => $_SESSION['users_management']['search_on'], + 'type_page' => 'users_management' + ]); + } + + public function viewReferencesManagement(Request $req, Response $res, array $args) + { + $get = $req->getQueryParams(); + + $refs_tab = $this->loadRefs('reference_management', false); + $references = $refs_tab['references']; + $dyn_refs = $refs_tab['dyn_refs']; + + $ref_ref = new ReferenceModel; + $ref = $ref_ref->newInstance(); + foreach ($references as $reference) { + $arr_ref_id_user[$reference['attributes']['id']] = $ref->findUsername($reference['attributes']['id']); + $mails = $ref->findMails($reference['attributes']['id']); + if ($mails !== false) { + $ref_user_mails[$reference['attributes']['id']] = $mails; + } else { + $ref_user_mails[$reference['attributes']['id']] = null; + } + } + + $references->setPath($this->container->router->pathFor('adminReferencesManagement')); + + // render in twig view + $this->render($this->container->project->pathFor('adminReferencesManagement.html.twig'), [ + 'class' => 'admin', + 'showmodal' => isset($get['showmodal']), + 'uuid' => isset($get['uuid']) ? $get['uuid'] : '', + 'references' => $references, + 'pagination' => $_SESSION['reference_management']['pagination'], + 'orderby' => $_SESSION['reference_management']['orderby'], + 'sort' => $_SESSION['reference_management']['sort'], + 'dyn_refs' => $dyn_refs, + 'user_session' => $_SESSION['user'], + 'actions' => $this->getReferencesActions(), + 'customFilter' => $_SESSION['reference_management']['customFilter'], + 'search' => $_SESSION['reference_management']['search'], + 'action_code' => $_SESSION['reference_management']['action_code'], + 'search_on' => $_SESSION['reference_management']['search_on'], + 'type_page' => 'reference_management', + 'ref_user_mails'=> json_encode($ref_user_mails), + 'arr_ref_id_user'=> $arr_ref_id_user + ]); + } + + public function prepareMails(Request $req, Response $res) + { + $post = $req->getParsedBody(); + $tmp = []; + if (isset($post['checkboxAdminActionForm1'])) { + $tmp[] = $post['checkboxAdminActionForm1']; + } + if (isset($post['checkboxAdminActionForm2'])) { + $tmp[] = $post['checkboxAdminActionForm2']; + } + if (isset($post['inputrow3col2'])) { + $tmp[] = $post['inputrow3col2']; + } + + foreach ($tmp as $key => $value) { + $this->sendMail( + $req, + $res, + [ + 'ref_id' => $post['ref_id_input'], + 'comment' => $post['comment'], + 'mail' => $value + ] + ); + } + return $res->withRedirect($this->container->router->pathFor('adminReferencesManagement')); + } + + public function sendMail(Request $req, Response $res, array $args) + { + $mail_to = $args['mail']; + $ref = new ReferenceModel(); + $ref_model = $ref->newInstance(); + + $join_table = $this->container->project->getSlug() . '_reference'; + + $res_ref = $ref_model->where("reference.id", "=", $args['ref_id']) + ->leftJoin($join_table, $join_table.'.reference_id', '=', 'reference.id') + ->firstOrFail(); + + if (isset($args['comment']) && !empty($args['comment'])) { + $admin_msg = "Administrator's message :\n".$args['comment']; + } else { + $admin_msg = ""; + } + + $msg_ref = + " + Name : " . $res_ref['attributes']['name'] ."\n + Country : " . $res_ref['attributes']['country'] ."\n + Assets : " . $res_ref['attributes']['num_assets'] ."\n + Helpdesk : " . $res_ref['attributes']['num_helpdesk'] ."\n + Registration date : " . date("d M Y, h:i a", strtotime($res_ref['attributes']['created_at'])) ."\n + Comment : " . $res_ref['attributes']['comment']."\n"; + + $msg = "The administrator send you a message about your reference below :\n$msg_ref\n$admin_msg"; + + // prepare mail + $mail = new \PHPMailer; + $mail->setFrom($this->container['settings']['mail_admin']); + $mail->addAddress($mail_to); + $mail->Subject = "A new message from telemetry site :"; + $mail->Body = $msg; + $send_ok = $mail->send(); + + if ($send_ok === false) { + $this->container->flash->addMessage( + "error", + "Error sending the mail to $mail_to.\n".$mail->ErrorInfo + ); + } + } + + public function getUsersActions() + { + return [ + ['code' => 'to_admin', 'msg' => 'Upgrade user to admin'], + ['code' => 'to_not_admin', 'msg' => 'Downgrade this admin user'] + ]; + } + + public function getReferencesActions() + { + return [ + ['code' => 'to_denied', 'msg' => 'Status to denied'], + ['code' => 'to_pending', 'msg' => 'Status to pending'], + ['code' => 'to_accepted', 'msg' => 'Status to accepted'] + ]; + } +} diff --git a/app/Controllers/Connection.php b/app/Controllers/Connection.php new file mode 100644 index 0000000..bf53e2e --- /dev/null +++ b/app/Controllers/Connection.php @@ -0,0 +1,68 @@ + $req->isXhr()]; + + if ($req->isXhr()) { + $slimGuard = $this->container['csrf']; + $slimGuard->validateStorage(); + // Generate new tokens + $csrfNameKey = $slimGuard->getTokenNameKey(); + $csrfValueKey = $slimGuard->getTokenValueKey(); + $keyPair = $slimGuard->generateToken(); + + $params += [ + 'class' => 'popup-connection', + 'my_csrf' => [ + 'name' => $keyPair['csrf_name'], + 'value' => $keyPair['csrf_value'] + ] + ]; + } + $this->render( + $this->container->project->pathFor('connection.html.twig'), + $params + ); + } + + public function send(Request $req, Response $res, $redirect = 'telemetry') + { + $post = $req->getParsedBody(); + + $post['user'] = htmlentities($post['user']); + + $auth_ref = new AuthenticationModel; + $auth = $auth_ref->newInstance(); + + if ($auth->authenticate($post)) { + $_SESSION['user'] = $auth->getUser()['attributes']; + + //redirect + return $res->withRedirect($this->container->router->pathFor($redirect)); + } else { + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'warn', + 'Wrong username or password' + ); + //redirect + return $res->withRedirect($this->container->router->pathFor('telemetry')); + } + } + + public function disconnect(Request $req, Response $res) + { + unset($_SESSION['user']); + return $res->withRedirect($this->container->router->pathFor('telemetry')); + } +} diff --git a/app/Controllers/Filters.php b/app/Controllers/Filters.php new file mode 100644 index 0000000..972ba37 --- /dev/null +++ b/app/Controllers/Filters.php @@ -0,0 +1,68 @@ +setDefaultFilters('orderby', 'created_at', $_SESSION[$management_name], $args); + $_SESSION[$management_name] = $this->setDefaultFilters('sort', 'desc', $_SESSION[$management_name], $args); + $_SESSION[$management_name] = $this->setDefaultFilters('pagination', 10, $_SESSION[$management_name], $args); + $_SESSION[$management_name] = $this->setDefaultFilters('search', "null", $_SESSION[$management_name], $args); + $_SESSION[$management_name] = $this->setDefaultFilters('action_code', "null", $_SESSION[$management_name], $args); + + switch ($management_name) { + case 'users_management': + $_SESSION[$management_name] = $this->setDefaultFilters('customFilter', "null", $_SESSION[$management_name], $args); + $_SESSION[$management_name]['search_on'] = 'Username'; + break; + + case 'reference_management': + case 'profile': + $_SESSION[$management_name] = $this->setDefaultFilters('customFilter', 1, $_SESSION[$management_name], $args); + $_SESSION[$management_name]['search_on'] = 'Name'; + break; + } + + if (isset($args['orderby']) && $_SESSION[$management_name]['orderby'] == $args['orderby']) { + // toggle sort if orderby requested on the same column + $_SESSION[$management_name]['sort'] = ($_SESSION[$management_name]['sort'] == "desc" + ? "asc" + : "desc"); + } + } + + return $this->typePageRedirect($req, $res, $management_name); + } + + public function setDefaultFilters($filter_name, $default_value, $session_ref, $args) + { + if (isset($args[$filter_name])) { + $session_ref[$filter_name] = $args[$filter_name]; + } elseif (isset($session_ref[$filter_name])) { + $session_ref[$filter_name] = $session_ref[$filter_name]; + } else { + $session_ref[$filter_name] = $default_value; + } + return $session_ref; + } +} diff --git a/app/Controllers/PageAbstract.php b/app/Controllers/PageAbstract.php new file mode 100644 index 0000000..99e9956 --- /dev/null +++ b/app/Controllers/PageAbstract.php @@ -0,0 +1,284 @@ +container->project->getDynamicReferences(); + if (false === $dyn_refs) { + // retrieve data from model + $references = ReferenceModel::active()->orderBy( + $_SESSION[$management_name]['orderby'], + $_SESSION[$management_name]['sort'] + )->paginate($_SESSION[$management_name]['pagination']); + } else { + try { + $join_table = $this->container->project->getSlug() . '_reference'; + $order_field = $_SESSION[$management_name]['orderby']; + $order_table = (isset($dyn_refs[$order_field]) ? $join_table : 'reference'); + // retrieve data from model + $ref = new ReferenceModel(); + $model = $ref->newInstance(); + $model = call_user_func_array( + [ + $model, + 'select' + ], + array_merge( + ['reference.*'], + array_map( + function ($key) use ($join_table) { + return $join_table . '.' . $key; + }, + array_keys($dyn_refs) + ) + ) + ); + $model->where('status', '=', $status); + if ($user_id != null) { + $model->where('user_id', '=', $user_id); + } + $search = $_SESSION[$management_name]['search']; + if ($search != 'null') { + $model->whereRaw('LOWER("'.strtolower($_SESSION[$management_name]['search_on']).'") LIKE ? ', ['%'.htmlentities(strtolower($search)).'%']); + } + + if ($order_field != null) { + $model->orderBy( + $order_table . '.' . $order_field, + $_SESSION[$management_name]['sort'] + ); + } + $model->leftJoin($join_table, 'reference.id', '=', $join_table . '.reference_id'); + $references = $model->paginate($_SESSION[$management_name]['pagination']); + } catch (\Illuminate\Database\QueryException $e) { + if ($e->getCode() == '42P01') { + //relation does not exists + throw new \RuntimeException( + 'You have configured dynamic references for your project; but table ' . + $join_table . ' is missing!', + 0, + $e + ); + } + throw $e; + } + } + return ['references' => $references, 'dyn_refs' => $dyn_refs]; + } + + /** + * Load users from database based on filters controller + * + * @param String $order_field + * + * @return GLPI\Telemetry\Models\User + */ + public function loadUsers($order_field = 'username') + { + $ref = new UserModel(); + $model = $ref->newInstance(); + $is_admin = $model->stringBoolAdmin($_SESSION['users_management']['customFilter']); + $search = $_SESSION['users_management']['search']; + $model = call_user_func_array( + [ + $model, + 'select' + ], + ['users.*'] + ); + + if ($is_admin !== null) { + $model->where('is_admin', '=', $is_admin); + } + + if ($search != 'null') { + $model->whereRaw('LOWER("'.strtolower($_SESSION['users_management']['search_on']).'") LIKE ? ', ['%'.htmlentities(strtolower($search)).'%']); + } + + $model->orderBy( + $order_field, + $_SESSION['users_management']['sort'] + ); + $users = $model->paginate($_SESSION['users_management']['pagination']); + + foreach ($users as $key => $user) { + $user['attributes'] = + $user['attributes'] + + ['refs_count'=>$this->loadUserRefsCount($user['attributes']['id'])]; + } + + return $users; + } + + /** + * Update reference status + * + * @param integer $user_id + * + * @return GLPI\Telemetry\Models\Reference + */ + public function loadUserRefsCount($user_id = null) + { + if ($user_id == null) { + $user_id = $_SESSION['user']['id']; + } + + //Reload SESSION variables for user's references + $ref = new ReferenceModel(); + $ref_model = $ref->newInstance(); + return $ref_model->where('user_id', $user_id)->get()->count(); + } + + /** + * Associating for any action code an array for the update + * + * @param String $action + * + * @return array + */ + public function actionsToUpdateArray($action) + { + switch ($action) { + case 'to_admin': + return ['is_admin' => true]; + break; + + case 'to_not_admin': + return ['is_admin' => false]; + break; + + case 'to_pending': + return ['status' => ReferenceModel::PENDING]; + break; + + case 'to_denied': + return ['status' => ReferenceModel::DENIED]; + break; + + case 'to_accepted': + return ['status' => ReferenceModel::ACCEPTED]; + break; + + default: + return null; + break; + } + } + + /** + * Make the action for admin management + * + * @param array $args Specidied the type page : 'reference_management', 'users_management', 'profile' + * + * @return Slim\Http\Response + */ + public function doActions(Request $req, Response $res, $args) + { + $post = $req->getParsedBody(); + unset($post['csrf_name']); + unset($post['csrf_value']); + + foreach ($post as $key => $value) { + $tmp = explode("-", $key); + switch ($tmp[0]) { + case 'select': + //$actions[object.id] = action.code + $actions[$tmp[1]] = $value; + break; + case 'checkbox': + $objects_id[] = $tmp[1]; + break; + + default: + $res + ->write($container->flash->addMessage('error', 'Something went wrong, you were redirected.')) + ->withRedirect($container->router->pathFor('telemetry')); + break; + } + } + + switch ($args['type_page']) { + case 'users_management': + $ref = new UserModel(); + break; + + case 'reference_management': + $ref = new ReferenceModel(); + break; + + default: + $res + ->write($container->flash->addMessage('error', 'Something went wrong, you were redirected.')) + ->withRedirect($container->router->pathFor('telemetry')); + break; + } + + $model = $ref->newInstance(); + + foreach ($actions as $object_id => $action) { + if (in_array($object_id, $objects_id)) { + $arrayActions = $this->actionsToUpdateArray($action); + if ($arrayActions === null) { + return false; + } else { + $action_res = $model->where('id', '=', $object_id)->update($arrayActions); + } + } + } + unset($post); + return $this->typePageRedirect($req, $res, $args['type_page']); + } + + /** + * Make the action for admin management + * + * @param String $type_page Specidied the type page : 'reference_management', 'users_management', 'profile' + * + * @return Slim\Http\Response + */ + public function typePageRedirect(Request $req, Response $res, $type_page) + { + switch ($type_page) { + case 'users_management': + return $res->withRedirect($this->container->router->pathFor('adminUsersManagement')); + break; + + case 'reference_management': + return $res->withRedirect($this->container->router->pathFor('adminReferencesManagement')); + break; + + case 'profile': + return $res->withRedirect($this->container->router->pathFor('profile')); + break; + + case 'reference': + return $res->withRedirect($this->container->router->pathFor('reference')); + break; + + default: + return $res->withRedirect($this->container->router->pathFor('telemetry')); + break; + } + } +} diff --git a/app/Controllers/Profile.php b/app/Controllers/Profile.php new file mode 100644 index 0000000..9beae57 --- /dev/null +++ b/app/Controllers/Profile.php @@ -0,0 +1,117 @@ +getQueryParams(); + + //Reload SESSION variables for user's references + $_SESSION['user']['references_count'] = $this->loadUserRefsCount(); + + $refs_tab = $this->loadRefs('profile', $_SESSION['user']['id']); + $references = $refs_tab['references']; + $dyn_refs = $refs_tab['dyn_refs']; + + $references->setPath($this->container->router->pathFor('profile')); + + // render in twig view + $this->render($this->container->project->pathFor('profile.html.twig'), [ + 'class' => 'profile', + 'uuid' => isset($get['uuid']) ? $get['uuid'] : '', + 'references' => $references, + 'pagination' => $_SESSION['profile']['pagination'], + 'orderby' => $_SESSION['profile']['orderby'], + 'sort' => $_SESSION['profile']['sort'], + 'dyn_refs' => $dyn_refs, + 'user_session' => (object) $_SESSION['user'], + 'status_page' => $_SESSION['profile']['customFilter'], + 'customFilter' => $_SESSION['profile']['customFilter'], + 'search' => $_SESSION['profile']['search'], + 'search_on' => $_SESSION['profile']['search_on'], + 'type_page' => 'profile' + ]); + } + + public function userUpdate(Request $req, Response $res) + { + $post = $req->getParsedBody(); + + $user = utf8_encode($post['name']); + $user = htmlentities($post['name']); + + + + $mail = utf8_encode($post['mail']); + $mail = htmlentities($post['mail']); + + $pass = utf8_encode($post['new_password']); + $pass = htmlentities($post['new_password']); + + $confirm_pass = utf8_encode($post['confirm_password']); + $confirm_pass = htmlentities($post['confirm_password']); + + $user_ref = new UserModel(); + $user_model = $user_ref->newInstance(); + + $register_ref = new RegisterModel(); + $register_model = $register_ref->newInstance(); + + $tmp = + [ + 'username' => $user, + 'email' => $mail + ]; + + if (empty($pass) xor empty($confirm_pass) || $pass !== $confirm_pass || !$register_model->isValidPassword($pass)) { + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'warn', + 'There is a problem with your password. Can\'t update your profile' + ); + // redirect to ok page + return $res->withRedirect($this->container->router->pathFor('profile')); + } elseif (!empty($pass) && !empty($confirm_pass)) { + $tmp['hash'] = password_hash($pass, PASSWORD_DEFAULT); + } + + + + if (!empty($user) && preg_match('/[a-zA-Z]/', $user)) { + if ($user_model->usernameExist($user) && $user != $_SESSION['user']['username']) { + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'warn', + 'This username already exist. Can\'t update your profile' + ); + // redirect to ok page + return $res->withRedirect($this->container->router->pathFor('profile')); + } + $user_model->where('username', '=', $_SESSION['user']['username'])->update($tmp); + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'success', + 'Update done !' + ); + + //reload user informations + $_SESSION['user'] = $user_model->getUser($user)['attributes']; + } else { + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'warn', + 'You must fill the username field with letters to update your profile.' + ); + } + + // redirect to ok page + return $res->withRedirect($this->container->router->pathFor('profile')); + } +} diff --git a/app/Controllers/Reference.php b/app/Controllers/Reference.php index c044ee3..7ba837c 100644 --- a/app/Controllers/Reference.php +++ b/app/Controllers/Reference.php @@ -1,93 +1,25 @@ getQueryParams(); - // default session param for this controller - if (!isset($_SESSION['reference'])) { - $_SESSION['reference'] = [ - "orderby" => 'created_at', - "sort" => "desc" - ]; - } - - // manage sorting - if (isset($get['orderby'])) { - if ($_SESSION['reference']['orderby'] == $get['orderby']) { - // toggle sort if orderby requested on the same column - $_SESSION['reference']['sort'] = ($_SESSION['reference']['sort'] == "desc" - ? "asc" - : "desc"); - } - $_SESSION['reference']['orderby'] = $get['orderby']; - } - $_SESSION['reference']['pagination'] = 15; - - //check for refences presence - $dyn_refs = $this->container->project->getDynamicReferences(); - if (false === $dyn_refs) { - // retrieve data from model - $references = ReferenceModel::active()->orderBy( - $_SESSION['reference']['orderby'], - $_SESSION['reference']['sort'] - )->paginate($_SESSION['reference']['pagination']); - } else { - try { - $join_table = $this->container->project->getSlug() . '_reference'; - $order_field = $_SESSION['reference']['orderby']; - $order_table = (isset($dyn_refs[$order_field]) ? $join_table : 'reference'); - // retrieve data from model - $ref = new ReferenceModel(); - $model = $ref->newInstance(); - $model = call_user_func_array( - [ - $model, - 'select' - ], - array_merge( - ['reference.*'], - array_map( - function ($key) use ($join_table) { - return $join_table . '.' . $key; - }, - array_keys($dyn_refs) - ) - ) - ); - $model->where('is_displayed', '=', true); - $model->orderBy( - $order_table . '.' . $order_field, - $_SESSION['reference']['sort'] - ) - ->leftJoin($join_table, 'reference.id', '=', $join_table . '.reference_id') - ; - $references = $model->paginate($_SESSION['reference']['pagination']); - } catch (\Illuminate\Database\QueryException $e) { - if ($e->getCode() == '42P01') { - //rlation does not exists - throw new \RuntimeException( - 'You have configured dynamic references for your project; but table ' . - $join_table . ' is missing!', - 0, - $e - ); - } - throw $e; - } - } + $refs_tab = $this->loadRefs('reference', null, ReferenceModel::ACCEPTED); + $references = $refs_tab['references']; + $dyn_refs = $refs_tab['dyn_refs']; $references->setPath($this->container->router->pathFor('reference')); + $user = (isset($_SESSION['user']) ? $_SESSION['user'] : null); // render in twig view $this->render($this->container->project->pathFor('reference.html.twig'), [ @@ -99,7 +31,9 @@ function ($key) use ($join_table) { 'pagination' => $references->appends($_GET)->render(), 'orderby' => $_SESSION['reference']['orderby'], 'sort' => $_SESSION['reference']['sort'], - 'dyn_refs' => $dyn_refs + 'dyn_refs' => $dyn_refs, + 'user' => $user, + 'type_page' => 'reference' ]); } @@ -127,6 +61,11 @@ public function register(Request $req, Response $res) // alter data $ref_data['country'] = strtolower($ref_data['country']); + if ($_SESSION['user'] != null) { + $ref_data['user_id'] = $_SESSION['user']['id']; + } else { + $ref_data['user_id'] = null; + } // create reference in db if ('' == $ref_data['uuid']) { @@ -177,21 +116,96 @@ public function register(Request $req, Response $res) return $res->withRedirect($this->container->router->pathFor('reference')); } - public function filter(Request $req, Response $res, array $args) + public function update(Request $req, Response $res) { - $get = $req->getQueryParams(); + $post = $req->getParsedBody(); + + // clean data + unset($post['g-recaptcha-response']); + unset($post['csrf_name']); + unset($post['csrf_value']); + + $ref_data = $post; + $dyn_data = []; - // manage sorting - if (isset($args['orderby'])) { - if ($_SESSION['reference']['orderby'] == $args['orderby']) { - // toggle sort if orderby requested on the same column - $_SESSION['reference']['sort'] = ($_SESSION['reference']['sort'] == "desc" - ? "asc" - : "desc"); + $dyn_ref = $this->container->project->getDynamicReferences(); + if (false !== $dyn_ref) { + foreach (array_keys($dyn_ref) as $ref) { + if (isset($post[$ref])) { + $dyn_data[$ref] = (int)$post[$ref]; + unset($ref_data[$ref]); + } } - $_SESSION['reference']['orderby'] = $args['orderby']; } - return $res->withRedirect($this->container->router->pathFor('reference')); + // alter data + $ref_data['country'] = strtolower($ref_data['country']); + $ref_data['status'] = 1; + if ($_SESSION['user'] != null) { + $ref_data['user_id'] = $_SESSION['user']['id']; + } else { + $ref_data['user_id'] = null; + } + + //ref + $reference = ReferenceModel::updateOrCreate( + ['id' => $ref_data['id']], + $ref_data + ); + + $ref = new ReferenceModel(); + $model = $ref->newInstance(); + $model->updateStatus($reference['id'], 1); + + //dynamic ref + $dref = new DynamicReference(); + $dynamics = $dref->newInstance(); + $dynamics->setTable($this->container->project->getSlug() . '_reference'); + + $exists = $dynamics->where('reference_id', $reference['id'])->get(); + + if (1 === $exists->count()) { + $dynamics + ->where('reference_id', '=', $reference['id']) + ->update($dyn_data); + + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'success', + 'Update done !' + ); + } else { + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'warn', + 'Can\'t update your reference, please contact an administrator.' + ); + } + + // redirect to ok page + return $res->withRedirect($this->container->router->pathFor('profile')); + } + + public function delete(Request $req, Response $res) + { + $post = $req->getParsedBody(); + + $dref = new DynamicReference(); + $dynamics = $dref->newInstance(); + $dynamics->setTable($this->container->project->getSlug() . '_reference'); + $dynamics->where('reference_id', $post['ref_id'])->forceDelete(); + + $ref = new ReferenceModel(); + $model = $ref->newInstance(); + $model->where('id', $post['ref_id'])->forceDelete(); + + // store a message for user (displayed after redirect) + $this->container->flash->addMessage( + 'success', + 'Successful deletion !' + ); + + // redirect to ok page + return $res->withRedirect($this->container->router->pathFor('profile')); } } diff --git a/app/Controllers/Register.php b/app/Controllers/Register.php new file mode 100644 index 0000000..3ac24c0 --- /dev/null +++ b/app/Controllers/Register.php @@ -0,0 +1,44 @@ +render($this->container->project->pathFor('register.html.twig'), [ + 'class' => 'register' + ]); + } + + public function send(Request $req, Response $res) + { + $post = $req->getParsedBody(); + + $register_ref = new RegisterModel; + $register_model = $register_ref->newInstance(); + + $tab = $register_model->checkRegister($post); + + if ($tab['status'] === '200') { + $type = 'success'; + $redirect = 'connection'; + } else { + $type = 'error'; + $redirect = 'register'; + } + + $msg_text = $tab['msg']; + $this->container->flash->addMessage( + $type, + $msg_text + ); + + + //redirect + return $res->withRedirect($this->container->router->pathFor($redirect)); + } +} diff --git a/app/Models/Authentication.php b/app/Models/Authentication.php new file mode 100644 index 0000000..4641e4a --- /dev/null +++ b/app/Models/Authentication.php @@ -0,0 +1,63 @@ +isExist($post) != false) { + return true; + } else { + return false; + } + } + + /** + * Get the current user + * + * @return GLPI\Telemetry\Models\User + * @see isExist() + **/ + public function getUser() + { + return $this->user; + } + + /** + * Test if the username already exist in database, verify the password and build the user object + * + * @param array $post This is the informations from the connection form + * + * @return boolean|GLPI\Telemetry\Models\User + **/ + public function isExist($post) + { + $user_ref = new UserModel(); + $user_model = $user_ref->newInstance(); + $bool_username = $user_model->usernameExist($post['user']); + + if ($bool_username) { + $user_obj = $user_model::where('username', '=', $post['user'])->first(); + + $check_pw = password_verify($post['password'], $user_obj->hash); + if ($check_pw) { + $this->user = $user_obj; + return $user_obj; + } + } + return false; + } +} diff --git a/app/Models/DynamicReference.php b/app/Models/DynamicReference.php index 524dc38..d38629c 100644 --- a/app/Models/DynamicReference.php +++ b/app/Models/DynamicReference.php @@ -11,6 +11,7 @@ class DynamicReference extends \Illuminate\Database\Eloquent\Model * Set the table associated with the model. * * @param string $table + * * @return void */ public function setTable($table) diff --git a/app/Models/Reference.php b/app/Models/Reference.php index f42bf6c..8d8b6b9 100644 --- a/app/Models/Reference.php +++ b/app/Models/Reference.php @@ -1,11 +1,16 @@ where('is_displayed', '=', true); + return $query->where('status', '=', self::ACCEPTED); + } + + /** + * Update reference status + * + * @param integer $id Reference id + * @param integer $status New reference status + * + * @return \Illuminate\Database\Eloquent\Builder + */ + public function updateStatus($id, $status) + { + return $this::where('id', '=', $id)->update(['status' => $status]); + } + + + /** + * Find emails from user and reference + * + * @param integer $ref_id + * + * @return array + **/ + public function findMails($ref_id) + { + $ref_user = new UserModel(); + $user = $ref_user->newInstance(); + + $res_ref = $this::where('id', '=', $ref_id)->first(); + $ref_mail = ($res_ref === null) ? null : $res_ref->attributes['email']; + $ref_user_id = $res_ref->attributes['user_id']; + + $res_user = $user::where('id', '=', $ref_user_id)->first(); + $user_mail = ($res_user === null) ? null : $res_user->attributes['email']; + + return + [ + 'user_mail' => $user_mail, + 'ref_mail' => $ref_mail + ]; + } + + /** + * Find Username from reference's id + * + * @param integer $ref_id Reference's id + * + * @return String + */ + public function findUsername($ref_id) + { + $ref_user = new UserModel(); + $user = $ref_user->newInstance(); + + $res_ref = $this::where('id', '=', $ref_id)->first(); + $ref_user_id = $res_ref->attributes['user_id']; + + $res_user = $user::where('id', '=', $ref_user_id)->first(); + return ($res_user === null) ? null : $res_user->attributes['username']; + } + + /** + * Match between the constant and the string value for status + * + * @param integer $status + * + * @return String|boolean + **/ + public function statusIntToText($status) + { + switch ($status) { + case self::DENIED: + return "denied"; + break; + case self::PENDING: + return "pending"; + break; + case self::ACCEPTED: + return "accepted"; + break; + default: + return false; + } } } diff --git a/app/Models/Register.php b/app/Models/Register.php new file mode 100644 index 0000000..faaa4bd --- /dev/null +++ b/app/Models/Register.php @@ -0,0 +1,115 @@ + '', + 'msg' => '' + ]; + protected $guarded = [ + 'id' + ]; + + /** + * Check if the form's values from the registration page are correct and insert in database + * + * @param array $post Informations from the registration's form + * + * @return array + * @see insertRegister() + **/ + public function checkRegister($post) + { + $user = htmlentities($post['username']); + $hash = htmlentities($post['password']); + $mail = htmlentities($post['mail']); + $admin = false; + + if (!$this->isValidPassword($hash)) { + $this->setTabReturn('406', 'Password is not compliant'); + return $this->tab; + } + + $hash = password_hash($post['password'], PASSWORD_DEFAULT); + + return $this->insertRegister($user, $hash, $mail, $admin); + } + + + /** + * Length 8 chars + * At least one lowercase letter + * At least one uppercase letter + * At least one digit + * + * @param string $password + * + * @return boolean + **/ + public function isValidPassword($password) + { + return preg_match('#^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$#', $password) ? true : false; + } + + /** + * Create the new user by insert him in database + * + * @param string $user + * @param string $hash The hashed password + * @param string $mail + * @param boolean $admin + * + * @return array + **/ + private function insertRegister($user, $hash, $mail, $admin) + { + + // test if the user already exist + $user_ref = new UserModel(); + $user_model = $user_ref->newInstance(); + if ($user_model->usernameExist($user)) { + $this->setTabReturn('417', 'Registration failed, user already exist'); + return $this->tab; + } + + + $tmp = + [ + 'username' => $user, + 'hash' => $hash, + 'email' => $mail, + 'is_admin' => $admin + ] + ; + + + $status = $user_model->insert($tmp); + + if ($status === true) { + $this->setTabReturn('200', 'Registration done'); + return $this->tab; + } else { + $this->setTabReturn('417', 'Registration failed'); + return $this->tab; + } + } + + /** + * Status 200 OK + * Status 406 Not Acceptable + * Status 417 Expectation Failed + * + * @param integer $status + * @param string $msg + * + * @return void + **/ + private function setTabReturn($status, $msg) + { + $this->tab['status'] = $status; + $this->tab['msg'] = $msg; + } +} diff --git a/app/Models/User.php b/app/Models/User.php new file mode 100644 index 0000000..ca078d5 --- /dev/null +++ b/app/Models/User.php @@ -0,0 +1,84 @@ + $this->id, + 'username' => $this->username, + 'mail' => $this->mail, + 'is_admin' => $this->is_admin + ]; + } + + /** + * Return a user from database by his name + * + * @param string $name + * + * @return GLPI\Telemetry\Models\User + */ + public function getUser($name) + { + $user = $this::where('username', '=', $name)->first(); + return $user; + } + + /** + * Test if a username exist in database + * + * @param string $username + * + * @return boolean + */ + public function usernameExist($username) + { + if (! is_null($this->where('username', '=', $username)->first())) { + return true; + } else { + return false; + } + } + + /** + * Convert String to Boolean + * + * @param String $str Boolean as a string + * + * @return Boolean + */ + public function stringBoolAdmin($str) + { + switch ($str) { + case 'null': + return null; + break; + case 'true': + return true; + break; + case 'false': + return false; + break; + default: + return null; + break; + } + } +} diff --git a/app/Project.php b/app/Project.php index 65f0f40..2673dc0 100644 --- a/app/Project.php +++ b/app/Project.php @@ -2,6 +2,8 @@ namespace GLPI\Telemetry; +use GLPI\Telemetry\Models\User as UserModel; + class Project { private $name; @@ -14,6 +16,9 @@ class Project private $project_path; private $templates_path; private $enable_contact = true; + private $enable_profile = true; + private $enable_connection = true; + private $enable_admin = false; private $footer_links = [ 'GLPI project' => [ 'faclass' => 'fa fa-globe', @@ -86,6 +91,23 @@ public function __construct($name, $logger = null) ); $this->project_path = __DIR__ . '/../projects/' . $this->slug; $this->templates_path = $this->project_path . '/Templates'; + + //reload user's informations + if (isset($_SESSION['user'])) { + $user_ref = new UserModel; + $user_model = $user_ref->newInstance(); + $_SESSION['user'] = $user_model->getUser($_SESSION['user']['username'])['attributes']; + } + + if (isset($_SESSION['user']['username'])) { + $this->enable_profile = true; + if ($_SESSION['user']['is_admin']) { + $this->enable_admin = true; + } + } else { + $this->enable_profile = false; + $this->enable_admin = false; + } } /** @@ -107,6 +129,18 @@ public function setConfig($config) $this->enable_contact = (bool)$config['enable_contact']; } + if (isset($config['enable_profile'])) { + $this->enable_profile = (bool)$config['enable_profile']; + } + + if (isset($config['enable_connection'])) { + $this->enable_connection = (bool)$config['enable_connection']; + } + + if (isset($config['enable_admin'])) { + $this->enable_admin = (bool)$config['enable_admin']; + } + if (isset($config['schema'])) { $this->setSchemaConfig($config['schema']); } @@ -462,6 +496,46 @@ public function hasContactPage() return $this->enable_contact; } + /** + * Is connection page active for current project + * + * @return boolean + */ + public function hasConnectionPage() + { + return $this->enable_connection; + } + + /** + * Is register page active for current project + * + * @return boolean + */ + public function hasRegisterPage() + { + return !$this->enable_profile; + } + + /** + * Is profile page active for current project + * + * @return boolean + */ + public function hasProfilePage() + { + return $this->enable_profile; + } + + /** + * Is admin page active for current project + * + * @return boolean + */ + public function hasAdminPage() + { + return $this->enable_admin; + } + /** * Get footer links * diff --git a/app/Templates/default/adminReferencesManagement.html.twig b/app/Templates/default/adminReferencesManagement.html.twig new file mode 100644 index 0000000..0ffa35f --- /dev/null +++ b/app/Templates/default/adminReferencesManagement.html.twig @@ -0,0 +1,289 @@ +{% extends "partials/base.html.twig" %} +{% block title %}Admin{% endblock %} +{% block head %} + {{ parent() }} + + + +{% endblock %} + +{% block header %} +{% set myheader= { + 'title': ' Admin', + 'text': 'Manage references', + 'class': 'adminReferencesManagement' +} %} +{{ parent() }} +{% include('partials/adminNav.html.twig') %} +{% endblock %} + +{% block content %} +
+ {% include 'default/customResearch.html.twig' %} + +
+ This sort has loaded {{ references.total }} references. + + + + + + + + {% if dyn_refs|length > 0 %} + {% for key, labels in dyn_refs %} + + {% endfor %} + {% endif %} + + + + + + + {% for reference in references %} + + + + + {% if dyn_refs|length > 0 %} + {% for key in dyn_refs|keys %} + + {% endfor %} + {% endif %} + + + + + {% endfor %} + +
+ {% if orderby == 'name' %}{% endif %} + Name + + {% if orderby == 'country' %}{% endif %} + Country + + {% if orderby == key %}{% endif %} + {{labels.short_label}} + + {% if orderby == 'created_at' %}{% endif %} + Registration date + + Actions + + +
+ {% set data = { 'ref_id': reference.id, 'mails': ref_user_mails } %} + + + + {% if reference.url %} + {{reference.name}} + {% else %} + {{reference.name}} + {% endif %} + + + {{reference[key]}} + {{reference.created_at|date("Y-m-d") }} + + + + +
+ + {{ csrf.field | raw }} +
+ + + +
+ +
+ +{{ csrf.field | raw }} +
+ + + +
+ +
+{% endblock %} + + + +{% block userscripts %} +{{ parent() }} + + + + +{% endblock %} diff --git a/app/Templates/default/adminUsersManagement.html.twig b/app/Templates/default/adminUsersManagement.html.twig new file mode 100644 index 0000000..64e8398 --- /dev/null +++ b/app/Templates/default/adminUsersManagement.html.twig @@ -0,0 +1,103 @@ +{% extends "partials/base.html.twig" %} +{% block title %}Admin{% endblock %} +{% block head %} + {{ parent() }} + +{% endblock %} +{% block header %} +{% set myheader= { + 'title': ' Admin', + 'text': 'Manage users', + 'class': 'adminUsersManagement' +} %} +{{ parent() }} +{% include('partials/adminNav.html.twig') %} +{% endblock %} + +{% block content %} +
+ + {% include 'default/customResearch.html.twig' %} + +
+ This sort has loaded {{ users.total }} users. + + + + + + + + + + + + + + + {% for user in users %} + + + + + + + + + {% endfor %} + +
+ {% if orderby == 'username' %}{% endif %} + Username + + {% if orderby == 'email' %}{% endif %} + Email + + References count + + Admin + + Actions + +
+ +
+
+ {{ user.username|raw }} + + {{ user.email|raw }} + + {{ user.refs_count }} + + {% if user.is_admin == true %}Yes + {% else %}No + {% endif %} + + + + +
+ + {{ csrf.field|raw }} +
+ + +
+{% endblock %} + +{% block userscripts %} +{{ parent() }} +{% endblock %} + diff --git a/app/Templates/default/connection.html.twig b/app/Templates/default/connection.html.twig new file mode 100644 index 0000000..407c034 --- /dev/null +++ b/app/Templates/default/connection.html.twig @@ -0,0 +1,49 @@ +{% extends 'partials/' ~ (ajax ? 'ajax' : 'base') ~ '.html.twig' %} +{% block title %}Connection{% endblock %} + +{% block header %} +{% set myheader= { + 'title': ' Connection', + 'text': 'Connect to manage your references', +} %} +{{ parent() }} +{% endblock %} + +{% block content %} +
+ +
+
+ {% if my_csrf is not defined %}{% endif %} + +
+ +
+ {% if my_csrf is not defined %}{% endif %} + +
+ + + {% if my_csrf is defined %} + + + {% else %} + {{ csrf.field | raw }} + {% endif %} + + +
+ No account? Register now! +
+
+ +
+{% endblock %} + +{% block userscripts %} +{{ parent() }} + + + +{% endblock %} + diff --git a/app/Templates/default/customResearch.html.twig b/app/Templates/default/customResearch.html.twig new file mode 100644 index 0000000..4aaaa7a --- /dev/null +++ b/app/Templates/default/customResearch.html.twig @@ -0,0 +1,102 @@ + + + + {% if users is defined %} + + {% endif %} + {% if references is defined %} + + {% endif %} + {% if type_page == 'profile' %} + + {% endif %} + + + + + {% if actions is defined %} + + {% endif %} + + +
PaginationAdminStatusMassive actions
+ + + {% if users is defined %} + + {% endif %} + {% if references is defined %} + + {% endif %} + + + +
+ {% set val_search = '' %} + {% if search != 'null' %} + {% set val_search = search %} + {% endif %} + +
+ +
+
+
\ No newline at end of file diff --git a/app/Templates/default/profile.html.twig b/app/Templates/default/profile.html.twig new file mode 100644 index 0000000..2fe7900 --- /dev/null +++ b/app/Templates/default/profile.html.twig @@ -0,0 +1,343 @@ +{% extends "partials/base.html.twig" %} +{% block title %}Profile{% endblock %} +{% block head %} + {{ parent() }} + + +{% endblock %} + +{% block header %} +{% set myheader= { + 'title': ' Profile', + 'text': 'You can see here your global informations and your references.', +} %} +{{ parent() }} +{% endblock %} + +{% block content %} +
+ +

User's informations

+ + + + + + + + + + + + + + + + + {% if user_session.is_admin == true %} + {% else %} + {% endif %} + + + +
NameMailNumber of referencesAdmin
{{user_session.username|raw}}{{user_session.email|raw}}{{user_session.references_count}}YesNo
+ +

Your references

+ + {% include 'default/customResearch.html.twig' %} + + + + + + + + + + + + + + + {% for reference in references %} + + + + + + + + + + {% endfor %} + +
+ {% if orderby == 'name' %}{% endif %} + Name + + {% if orderby == 'country' %}{% endif %} + Country + + {% if orderby == 'created_at' %}{% endif %} + Registration date + + Mail + + Status +
+
+ {% if reference.url %} + {{reference.name}} + {% else %} + {{reference.name}} + {% endif %} +
+
+ + {{reference.created_at|date("Y-m-d") }} + + +
+ {% if reference.status == 1 %} {% endif %} + {% if reference.status == 0 %} {% endif %} + {% if reference.status == 2 %} {% endif %} +
+
+ + + +
+ + + + +
+ + {{ csrf.field | raw }} +
+ + + +
+ + {{ csrf.field | raw }} +
+ + + +
+ + {{ csrf.field | raw }} +
+ +
+{% endblock %} + +{% block userscripts %} +{{ parent() }} + + + + + +{% endblock %} diff --git a/app/Templates/default/reference.html.twig b/app/Templates/default/reference.html.twig index 053c9b2..f940218 100644 --- a/app/Templates/default/reference.html.twig +++ b/app/Templates/default/reference.html.twig @@ -7,11 +7,19 @@ {% endblock %} {% block header %} -{% set myheader= { +{% if user.id != null %} + {% set myheader= { 'title': ' References', 'text': 'We maintain a public database of registered %s installations. You may want register your own!'|format(project_name), -} %} + } %} +{% else %} + {% set myheader= { + 'title': ' References', + 'text': 'We maintain a public database of registered %s installations. + You may want register your own!'|format(project_name), + } %} +{% endif %} {{ parent() }} {% endblock %} @@ -25,23 +33,23 @@ {% if orderby == 'name' %}{% endif %} - Name + Name {% if orderby == 'country' %}{% endif %} - Country + Country {% if dyn_refs|length > 0 %} {% for key, labels in dyn_refs %} {% if orderby == key %}{% endif %} - {{labels.short_label}} + {{labels.short_label}} {% endfor %} {% endif %} {% if orderby == 'created_at' %}{% endif %} - Registration date + Registration date Comment @@ -81,6 +89,29 @@ {{ references.render() |raw }} +{% if user.id == null %} + +{% endif %} +