mirror of
https://github.com/danielbrendel/hortusfox-web.git
synced 2026-01-06 04:40:13 -06:00
Admin feature
This commit is contained in:
21
README.md
21
README.md
@@ -93,11 +93,11 @@ you can start it via:
|
||||
```shell
|
||||
php asatru serve
|
||||
```
|
||||
Now browse to http://localhost:8000/ and you should see a message indicating that the access is forbidden with error 403.
|
||||
At this point you need to create your database users. Go to your database control panel and switch to the users table.
|
||||
Add all new users that should get access to the application. The following is an example:
|
||||
Now browse to http://localhost:8000/ and you should be redirected to the authentication page.
|
||||
At this point you need to create your first user. Go to your database control panel and switch to the users table.
|
||||
Add the user account that should get access to the application with admin privileges. The following is an example:
|
||||
```sql
|
||||
INSERT INTO `users` (`id`, `name`, `email`, `password`, `password_reset`, `session`, `status`, `lang`, `chatcolor`, `show_log`, `last_seen_msg`, `last_typing`, `last_action`, `created_at`) VALUES
|
||||
INSERT INTO `users` (`id`, `name`, `email`, `password`, `password_reset`, `session`, `status`, `admin`, `lang`, `chatcolor`, `show_log`, `last_seen_msg`, `last_typing`, `last_action`, `created_at`) VALUES
|
||||
(
|
||||
NULL,
|
||||
'Username',
|
||||
@@ -106,6 +106,7 @@ INSERT INTO `users` (`id`, `name`, `email`, `password`, `password_reset`, `sessi
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
1,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
@@ -115,15 +116,17 @@ INSERT INTO `users` (`id`, `name`, `email`, `password`, `password_reset`, `sessi
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
As you might have noticed the values that you need to customize are name, email and password. All others are left with their default values.
|
||||
As you might have noticed the values that you need to customize are name, email, password and admin. All others are left with their default values.
|
||||
The password hash must be created manually. For testing purposes you might just want to quickly use something like:
|
||||
```shell
|
||||
php -r "echo password_hash('test', PASSWORD_BCRYPT);"
|
||||
```
|
||||
If you want to test it now you can again browse to the URL and the system will redirect you to the /auth page.
|
||||
After logging in, you should then be redirected to your dashboard. Users can change their passwords in their profile preferences. They can also
|
||||
reset their password. Therefore an e-mail will be sent to them with restoration instructions. Last but not least you need to add all your locations
|
||||
of your local environment to the database. Therefore go to the locations table and add your locatios:
|
||||
You may now login with your initial admin user account using your e-mail address and the password of which you have stored the hash in the table.
|
||||
After logging in, you should then be redirected to the dashboard. Further users can now be created via the admin area. Users can change their
|
||||
passwords in their profile preferences. They can also reset their password. Therefore an e-mail will be sent to them with restoration instructions.
|
||||
Each new created user will get a confirmation e-mail with an automatically generated password in order to log in. It is recommended that users change
|
||||
their passwords after their first login.
|
||||
Last but not least you need to add all your locations of your local environment to the database. Therefore go to the locations table and add your locatios:
|
||||
|
||||
```sql
|
||||
INSERT INTO `locations` (`id`, `name`, `icon`, `active`, `created_at`) VALUES
|
||||
|
||||
@@ -56,5 +56,10 @@ return [
|
||||
array('/chat/typing', 'ANY', 'index@get_chat_typing_status'),
|
||||
array('/chat/typing/update', 'ANY', 'index@update_chat_typing'),
|
||||
array('/user/online', 'ANY', 'index@get_online_users'),
|
||||
array('/admin', 'GET', 'admin@index'),
|
||||
array('/admin/environment/save', 'POST', 'admin@save_environment'),
|
||||
array('/admin/user/create', 'POST', 'admin@create_user'),
|
||||
array('/admin/user/update', 'POST', 'admin@update_user'),
|
||||
array('/admin/user/remove', 'ANY', 'admin@remove_user'),
|
||||
array('$404', 'ANY', 'error404@index')
|
||||
];
|
||||
|
||||
137
app/controller/admin.php
Normal file
137
app/controller/admin.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class represents your controller
|
||||
*/
|
||||
class AdminController extends BaseController {
|
||||
/**
|
||||
* Perform base initialization
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
if (!UserModel::isCurrentlyAdmin()) {
|
||||
header('Location: /');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles URL: /admin
|
||||
*
|
||||
* @param Asatru\Controller\ControllerArg $request
|
||||
* @return Asatru\View\ViewHandler
|
||||
*/
|
||||
public function index($request)
|
||||
{
|
||||
$user = UserModel::getAuthUser();
|
||||
$locs = LocationsModel::getAll();
|
||||
$user_accounts = UserModel::getAll();
|
||||
|
||||
return parent::view(['content', 'admin'], [
|
||||
'user' => $user,
|
||||
'locations' => $locs,
|
||||
'user_accounts' => $user_accounts
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles URL: /admin/environment/save
|
||||
*
|
||||
* @param Asatru\Controller\ControllerArg $request
|
||||
* @return Asatru\View\RedirectHandler
|
||||
*/
|
||||
public function save_environment($request)
|
||||
{
|
||||
try {
|
||||
$workspace = $request->params()->query('workspace', env('APP_WORKSPACE'));
|
||||
$lang = $request->params()->query('lang', env('APP_LANG'));
|
||||
$scroller = (bool)$request->params()->query('scroller', 0);
|
||||
$onlinetimelimit = (int)$request->params()->query('onlinetimelimit', env('APP_ONLINEMINUTELIMIT'));
|
||||
$chatonlineusers = (bool)$request->params()->query('chatonlineusers', 0);
|
||||
$chattypingindicator = (bool)$request->params()->query('chattypingindicator', 0);
|
||||
|
||||
UtilsModule::saveEnvironment($workspace, $lang, $scroller, $onlinetimelimit, $chatonlineusers, $chattypingindicator);
|
||||
|
||||
FlashMessage::setMsg('success', __('app.environment_settings_saved'));
|
||||
|
||||
return redirect('/admin');
|
||||
} catch (\Exception $e) {
|
||||
FlashMessage::setMsg('error', $e->getMessage());
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles URL: /admin/user/create
|
||||
*
|
||||
* @param Asatru\Controller\ControllerArg $request
|
||||
* @return Asatru\View\RedirectHandler
|
||||
*/
|
||||
public function create_user($request)
|
||||
{
|
||||
try {
|
||||
$name = $request->params()->query('name', null);
|
||||
$email = $request->params()->query('email', null);
|
||||
|
||||
UserModel::createUser($name, $email);
|
||||
|
||||
FlashMessage::setMsg('success', __('app.user_created_successfully'));
|
||||
|
||||
return redirect('/admin');
|
||||
} catch (\Exception $e) {
|
||||
FlashMessage::setMsg('error', $e->getMessage());
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles URL: /admin/user/update
|
||||
*
|
||||
* @param Asatru\Controller\ControllerArg $request
|
||||
* @return Asatru\View\RedirectHandler
|
||||
*/
|
||||
public function update_user($request)
|
||||
{
|
||||
try {
|
||||
$id = $request->params()->query('id');
|
||||
$name = $request->params()->query('name', null);
|
||||
$email = $request->params()->query('email', null);
|
||||
$admin = $request->params()->query('admin', 0);
|
||||
|
||||
UserModel::updateUser($id, $name, $email, (int)$admin);
|
||||
|
||||
FlashMessage::setMsg('success', __('app.user_updated_successfully'));
|
||||
|
||||
return redirect('/admin');
|
||||
} catch (\Exception $e) {
|
||||
FlashMessage::setMsg('error', $e->getMessage());
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles URL: /admin/user/remove
|
||||
*
|
||||
* @param Asatru\Controller\ControllerArg $request
|
||||
* @return Asatru\View\RedirectHandler
|
||||
*/
|
||||
public function remove_user($request)
|
||||
{
|
||||
try {
|
||||
$id = $request->params()->query('id');
|
||||
|
||||
UserModel::removeUser($id);
|
||||
|
||||
FlashMessage::setMsg('success', __('app.user_removed_successfully'));
|
||||
|
||||
return redirect('/admin');
|
||||
} catch (\Exception $e) {
|
||||
FlashMessage::setMsg('error', $e->getMessage());
|
||||
return back();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ return [
|
||||
'enter_password' => 'Gib dein Passwort ein',
|
||||
'enter_password_confirmation' => 'Bestätige dein Passwort',
|
||||
'login' => 'Anmelden',
|
||||
'logout' => 'Abmelden',
|
||||
'user_not_found' => 'User konnte nicht gefunden werden: {email}',
|
||||
'password_mismatch' => 'Die Passwörter stimmen nicht überein',
|
||||
'password' => 'Passwort',
|
||||
@@ -21,7 +22,7 @@ return [
|
||||
'restore_password' => 'Passwort wiederherstellen',
|
||||
'restore_password_info' => 'Bitte befolge die Anweisungen, die an dein E-Mail Konto geschickt wurden.',
|
||||
'reset_password' => 'Passwort zurücksetzen',
|
||||
'reset_password_hint' => 'Bitte navigiere zum folgenden Link, um deinen Zugriff auf {workspace} wiederzuerlangen: <a href="{url}">Zugang wiedererlangen</a>',
|
||||
'reset_password_hint' => 'Bitte navigiere zu folgendem Link, um deinen Zugriff auf {workspace} wiederzuerlangen: <a href="{url}">Zugang wiedererlangen</a>',
|
||||
'dashboard' => 'Dashboard',
|
||||
'welcome_message' => 'Hallo {name}, willkommen zurück!',
|
||||
'locations' => 'Räume',
|
||||
@@ -145,5 +146,24 @@ return [
|
||||
'no_photo_available' => 'Kein Foto verfügbar',
|
||||
'due' => 'Fällig',
|
||||
'overdue_tasks' => 'Überfällige Aufgaben',
|
||||
'view_task_details' => 'Gehe zu den Details'
|
||||
'view_task_details' => 'Gehe zu den Details',
|
||||
'admin_area' => 'Administration',
|
||||
'environment' => 'Environment',
|
||||
'workspace' => 'Arbeitsraum',
|
||||
'enable_scroller' => 'Scroller aktivieren',
|
||||
'online_time_limit' => 'Zeitlimit für Online-Status',
|
||||
'show_chat_onlineusers' => 'User anzeigen, die gerade online sind',
|
||||
'show_chat_typingindicator' => 'Indikator anzeigen, wenn jemand gerade im Chat schreibt',
|
||||
'admin' => 'Admin',
|
||||
'create' => 'Erstellen',
|
||||
'update' => 'Aktualisieren',
|
||||
'remove' => 'Entfernen',
|
||||
'create_user' => 'User erstellen',
|
||||
'account_created' => 'Konto wurde erstellt',
|
||||
'account_created_hint' => 'Dein Account für {workspace} wurde gerade erstellt. Bitte <a href="{url}">melde</a> mit deiner E-Mail Adresse und dem Passwort <strong>{password}</strong> an. Es wird dringend empfohlen, nach der Anmeldung dein Passwort zu ändern.',
|
||||
'environment_settings_saved' => 'Umgebungseinstellungen wurden erfolgreich gespeichert',
|
||||
'user_created_successfully' => 'Neuer User-Account wurde erfolgreich erstellt',
|
||||
'user_updated_successfully' => 'Die Daten wurden erfolgreich aktualisiert',
|
||||
'user_removed_successfully' => 'Das User-Konto wurde erfolgreich entfernt',
|
||||
'confirm_user_removal' => 'Soll dieser Account wirklich entfernt werden?'
|
||||
];
|
||||
@@ -14,6 +14,7 @@ return [
|
||||
'enter_password' => 'Enter your password',
|
||||
'enter_password_confirmation' => 'Confirm your password',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'user_not_found' => 'User not found: {email}',
|
||||
'password_mismatch' => 'The passwords do not match',
|
||||
'password' => 'Password',
|
||||
@@ -21,7 +22,7 @@ return [
|
||||
'restore_password' => 'Restore password',
|
||||
'restore_password_info' => 'Please follow the instructions that were sent to your E-Mail account.',
|
||||
'reset_password' => 'Reset password',
|
||||
'reset_password_hint' => 'Please navigate on the following link in order to reset your password for your access to {workspace}: <a href="{url}">Reset password</a>',
|
||||
'reset_password_hint' => 'Please navigate to the following link in order to reset your password for your access to {workspace}: <a href="{url}">Reset password</a>',
|
||||
'dashboard' => 'Dashboard',
|
||||
'welcome_message' => 'Hi {name}, welcome back!',
|
||||
'locations' => 'Locations',
|
||||
@@ -145,5 +146,24 @@ return [
|
||||
'no_photo_available' => 'No photo available',
|
||||
'due' => 'Due',
|
||||
'overdue_tasks' => 'Overdue tasks',
|
||||
'view_task_details' => 'View task details'
|
||||
'view_task_details' => 'View task details',
|
||||
'admin_area' => 'Admin area',
|
||||
'environment' => 'Environment',
|
||||
'workspace' => 'Workspace',
|
||||
'enable_scroller' => 'Enable scroller',
|
||||
'online_time_limit' => 'Online status time limit',
|
||||
'show_chat_onlineusers' => 'Show users that are currently online',
|
||||
'show_chat_typingindicator' => 'Show chat typing indicator',
|
||||
'admin' => 'Admin',
|
||||
'create' => 'Create',
|
||||
'update' => 'Update',
|
||||
'remove' => 'Remove',
|
||||
'create_user' => 'Create user',
|
||||
'account_created' => 'Account created',
|
||||
'account_created_hint' => 'Your account for {workspace} was just created. Please <a href="{url}">login</a> with your e-mail and the password <strong>{password}</strong>. It is strongly recommended to change your password after logging in.',
|
||||
'environment_settings_saved' => 'Saved environment settings successfully',
|
||||
'user_created_successfully' => 'New user was created successfully',
|
||||
'user_updated_successfully' => 'User data successfully updated',
|
||||
'user_removed_successfully' => 'The user account was removed successfully',
|
||||
'confirm_user_removal' => 'Do you really want to remove this user account?'
|
||||
];
|
||||
@@ -34,6 +34,7 @@ class UserModel_Migration {
|
||||
$this->database->add('password_reset VARCHAR(1024) NULL');
|
||||
$this->database->add('session VARCHAR(1024) NULL');
|
||||
$this->database->add('status BOOLEAN NOT NULL DEFAULT 0');
|
||||
$this->database->add('admin BOOLEAN NOT NULL DEFAULT 0');
|
||||
$this->database->add('lang VARCHAR(512) NULL');
|
||||
$this->database->add('chatcolor VARCHAR(512) NULL');
|
||||
$this->database->add('show_log BOOLEAN NOT NULL DEFAULT 1');
|
||||
|
||||
@@ -104,7 +104,7 @@ class UserModel extends \Asatru\Database\Model {
|
||||
$mailobj = new Asatru\SMTPMailer\SMTPMailer();
|
||||
$mailobj->setRecipient($email);
|
||||
$mailobj->setSubject(__('app.reset_password'));
|
||||
$mailobj->setView('mailreset', [], ['workspace' => env('APP_WORKSPACE'), 'token' => $reset_token]);
|
||||
$mailobj->setView('mail/mailreset', [], ['workspace' => env('APP_WORKSPACE'), 'token' => $reset_token]);
|
||||
$mailobj->send();
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
@@ -147,6 +147,23 @@ class UserModel extends \Asatru\Database\Model {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function isCurrentlyAdmin()
|
||||
{
|
||||
try {
|
||||
$user = static::getAuthUser();
|
||||
if ((!$user) || (!$user->get('admin'))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws \Exception
|
||||
@@ -373,6 +390,78 @@ class UserModel extends \Asatru\Database\Model {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getAll()
|
||||
{
|
||||
try {
|
||||
return static::raw('SELECT * FROM `' . self::tableName() . '`');
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $email
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function createUser($name, $email)
|
||||
{
|
||||
try {
|
||||
$password = substr(md5(random_bytes(55) . date('Y-m-d H:i:s')), 0, 10);
|
||||
|
||||
static::raw('INSERT INTO `' . self::tableName() . '` (name, email, password) VALUES(?, ?, ?)', [
|
||||
$name, $email, password_hash($password, PASSWORD_BCRYPT)
|
||||
]);
|
||||
|
||||
$mailobj = new Asatru\SMTPMailer\SMTPMailer();
|
||||
$mailobj->setRecipient($email);
|
||||
$mailobj->setSubject(__('app.account_created'));
|
||||
$mailobj->setView('mail/mailacccreated', [], ['workspace' => env('APP_WORKSPACE'), 'password' => $password]);
|
||||
$mailobj->send();
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $name
|
||||
* @param $email
|
||||
* @param $admin
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function updateUser($id, $name, $email, $admin)
|
||||
{
|
||||
try {
|
||||
static::raw('UPDATE `' . self::tableName() . '` SET name = ?, email = ?, admin = ? WHERE id = ?', [
|
||||
$name, $email, $admin, $id
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function removeUser($id)
|
||||
{
|
||||
try {
|
||||
static::raw('DELETE FROM `' . self::tableName() . '` WHERE id = ?', [
|
||||
$id
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated table name of the migration
|
||||
*
|
||||
|
||||
@@ -256,4 +256,52 @@ class UtilsModule {
|
||||
{
|
||||
return ($dt !== null) && (Carbon::parse($dt)->diffInSeconds() <= self::TYPING_SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $workspace
|
||||
* @param $lang
|
||||
* @param $scroller
|
||||
* @param $onlinetimelimit
|
||||
* @param $chatonlineusers
|
||||
* @param $chattypingindicator
|
||||
*/
|
||||
public static function saveEnvironment($workspace, $lang, $scroller, $onlinetimelimit, $chatonlineusers, $chattypingindicator)
|
||||
{
|
||||
$new_env_settings = [
|
||||
'APP_WORKSPACE' => $workspace,
|
||||
'APP_LANG' => $lang,
|
||||
'APP_ENABLESCROLLER' => $scroller,
|
||||
'APP_ONLINEMINUTELIMIT' => $onlinetimelimit,
|
||||
'APP_SHOWCHATONLINEUSERS' => $chatonlineusers,
|
||||
'APP_SHOWCHATTYPINGINDICATOR' => $chattypingindicator,
|
||||
];
|
||||
|
||||
foreach ($new_env_settings as $key => $value) {
|
||||
if (isset($_ENV[$key])) {
|
||||
$_ENV[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$env_content = "# Automatically generated at " . date('Y-m-d H:i:s') . "\n";
|
||||
|
||||
foreach ($_ENV as $key => $value) {
|
||||
if (gettype($value) === 'boolean') {
|
||||
$env_content .= $key . '=' . (($value) ? "true" : "false");
|
||||
} else if (gettype($value) === 'double') {
|
||||
$env_content .= $key . '=' . $value;
|
||||
} else if (gettype($value) === 'integer') {
|
||||
$env_content .= $key . '=' . $value;
|
||||
} else if (gettype($value) === 'string') {
|
||||
$env_content .= $key . '="' . $value . '"';
|
||||
} else if ($value === null) {
|
||||
$env_content .= $key . '=null';
|
||||
} else {
|
||||
$env_content .= $key . '=' . $value;
|
||||
}
|
||||
|
||||
$env_content .= "\n";
|
||||
}
|
||||
|
||||
file_put_contents(base_path() . '/.env', $env_content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ window.vue = new Vue({
|
||||
bShowEditInventoryItem: false,
|
||||
bShowManageGroups: false,
|
||||
bShowRestorePassword: false,
|
||||
bShowCreateNewUser: false,
|
||||
comboLocation: [],
|
||||
comboCuttingMonth: [],
|
||||
comboLightLevel: [],
|
||||
|
||||
@@ -1143,4 +1143,79 @@ a.navbar-burger:hover {
|
||||
|
||||
.reset-form input[type=submit] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.admin-environment {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.admin-environment h2 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.admin-environment label, .admin-environment span {
|
||||
color: rgb(150, 150, 150);
|
||||
}
|
||||
|
||||
.admin-environment input, .admin-environment select {
|
||||
color: rgb(150, 150, 150);
|
||||
background-color: rgb(50, 50, 50);
|
||||
}
|
||||
|
||||
.admin-users {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.admin-users h2 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.admin-users-list {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.admin-user-account {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.admin-user-account label, .admin-user-account span {
|
||||
color: rgb(150, 150, 150);
|
||||
}
|
||||
|
||||
.admin-user-account input, .admin-user-account select {
|
||||
color: rgb(150, 150, 150);
|
||||
background-color: rgb(50, 50, 50);
|
||||
}
|
||||
|
||||
.admin-user-account-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.admin-user-account-item-input {
|
||||
width: 34%;
|
||||
}
|
||||
|
||||
.admin-user-account-actions {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.admin-user-account-item-centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.admin-user-account-action-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.admin-users-actions {
|
||||
position: relative;
|
||||
margin-top: 20px;
|
||||
}
|
||||
107
app/views/admin.php
Normal file
107
app/views/admin.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<div class="columns">
|
||||
<div class="column is-2"></div>
|
||||
|
||||
<div class="column is-8 is-image-container" style="background-image: url('{{ asset('img/plants.jpg') }}');">
|
||||
<div class="column-overlay">
|
||||
<h1>{{ __('app.admin_area') }}</h1>
|
||||
|
||||
@include('flashmsg.php')
|
||||
|
||||
<div class="admin-environment">
|
||||
<h2>{{ __('app.environment') }}</h2>
|
||||
|
||||
<form method="POST" action="{{ url('/admin/environment/save') }}">
|
||||
@csrf
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ __('app.workspace') }}</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input" name="workspace" value="{{ env('APP_WORKSPACE') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ __('app.language') }}</label>
|
||||
<div class="control">
|
||||
<select class="input" name="lang">
|
||||
@foreach (UtilsModule::getLanguageList() as $lang)
|
||||
<option value="{{ $lang }}" {{ (env('APP_LANG') === $lang) ? 'selected' : ''}}>{{ $lang }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input type="checkbox" class="checkbox" name="scroller" value="1" {{ (env('APP_ENABLESCROLLER')) ? 'checked': '' }}> <span>{{ __('app.enable_scroller') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ __('app.online_time_limit') }}</label>
|
||||
<div class="control">
|
||||
<input type="number" class="input" name="onlinetimelimit" value="{{ env('APP_ONLINEMINUTELIMIT') }}" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input type="checkbox" class="checkbox" name="chatonlineusers" value="1" {{ (env('APP_SHOWCHATONLINEUSERS')) ? 'checked': '' }}> <span>{{ __('app.show_chat_onlineusers') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input type="checkbox" class="checkbox" name="chattypingindicator" value="1" {{ (env('APP_SHOWCHATTYPINGINDICATOR')) ? 'checked': '' }}> <span>{{ __('app.show_chat_typingindicator') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input type="submit" class="button is-success" value="{{ __('app.save') }}"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="admin-users">
|
||||
<h2>{{ __('app.users') }}</h2>
|
||||
|
||||
<div class="admin-users-list">
|
||||
@foreach ($user_accounts as $user_account)
|
||||
<div class="admin-user-account">
|
||||
<form method="POST" action="{{ url('/admin/user/update') }}">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{ $user_account->get('id') }}"/>
|
||||
|
||||
<div class="admin-user-account-item admin-user-account-item-input">
|
||||
<input type="text" class="input" name="name" value="{{ $user_account->get('name') }}"/>
|
||||
</div>
|
||||
|
||||
<div class="admin-user-account-item admin-user-account-item-input">
|
||||
<input type="email" class="input" name="email" value="{{ $user_account->get('email') }}"/>
|
||||
</div>
|
||||
|
||||
<div class="admin-user-account-item admin-user-account-item-centered">
|
||||
<input type="checkbox" name="admin" value="1" {{ ($user_account->get('admin')) ? 'checked' : '' }}/> <span>{{ __('app.admin') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="admin-user-account-actions">
|
||||
<span class="admin-user-account-action-item"><input type="submit" class="button is-success" value="{{ __('app.update') }}"/></span>
|
||||
<span class="admin-user-account-action-item"><a class="button is-danger" href="javascript:void(0);" onclick="if (confirm('{{ __('app.confirm_user_removal') }}')) { location.href = '{{ url('/admin/user/remove?id=' . $user_account->get('id')) }}'; }">{{ __('app.remove') }}</a></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="admin-users-actions">
|
||||
<span><a class="button is-info" href="javascript:void(0);" onclick="window.vue.bShowCreateNewUser = true;">{{ __('app.create') }}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-2"></div>
|
||||
</div>
|
||||
@@ -76,7 +76,7 @@
|
||||
<button class="delete" aria-label="close" onclick="window.vue.bShowRestorePassword = false;"></button>
|
||||
</header>
|
||||
<section class="modal-card-body is-stretched">
|
||||
<form id="frmEditText" method="POST" action="{{ url('/password/restore') }}">
|
||||
<form id="frmRestorePassword" method="POST" action="{{ url('/password/restore') }}">
|
||||
@csrf
|
||||
|
||||
<div class="field">
|
||||
@@ -87,7 +87,7 @@
|
||||
</form>
|
||||
</section>
|
||||
<footer class="modal-card-foot is-stretched">
|
||||
<button class="button is-success" onclick="this.innerHTML = '<i class=\'fas fa-spinner fa-spin\'></i> {{ __('app.loading_please_wait') }}'; document.getElementById('frmEditText').submit();">{{ __('app.restore_password') }}</button>
|
||||
<button class="button is-success" onclick="this.innerHTML = '<i class=\'fas fa-spinner fa-spin\'></i> {{ __('app.loading_please_wait') }}'; document.getElementById('frmRestorePassword').submit();">{{ __('app.restore_password') }}</button>
|
||||
<button class="button" onclick="window.vue.bShowRestorePassword = false;">{{ __('app.cancel') }}</button>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
@@ -645,6 +645,39 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" :class="{'is-active': bShowCreateNewUser}">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head is-stretched">
|
||||
<p class="modal-card-title">{{ __('app.create_user') }}</p>
|
||||
<button class="delete" aria-label="close" onclick="window.vue.bShowCreateNewUser = false;"></button>
|
||||
</header>
|
||||
<section class="modal-card-body is-stretched">
|
||||
<form id="frmCreateNewUser" method="POST" action="{{ url('/admin/user/create') }}">
|
||||
@csrf
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ __('app.name') }}</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input" name="name" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ __('app.email') }}</label>
|
||||
<div class="control">
|
||||
<input type="email" class="input" name="email" required>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<footer class="modal-card-foot is-stretched">
|
||||
<button class="button is-success" onclick="this.innerHTML = '<i class=\'fas fa-spinner fa-spin\'></i> {{ __('app.loading_please_wait') }}'; document.getElementById('frmCreateNewUser').submit();">{{ __('app.create') }}</button>
|
||||
<button class="button" onclick="window.vue.bShowCreateNewUser = false;">{{ __('app.cancel') }}</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('scroller.php')
|
||||
</div>
|
||||
|
||||
|
||||
20
app/views/mail/mailacccreated.php
Normal file
20
app/views/mail/mailacccreated.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ getLocale() }}">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
|
||||
<title>{{ __('app.account_created') }}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{ __('app.account_created') }}</h1>
|
||||
|
||||
<p>
|
||||
{!! __('app.account_created_hint', ['workspace' => $workspace, 'url' => url('/auth'), 'password' => $password]) !!}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<small>Powered by {{ env('APP_NAME') }}</small>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,5 +12,9 @@
|
||||
<p>
|
||||
{!! __('app.reset_password_hint', ['workspace' => $workspace, 'url' => url('/password/reset?token=' . $token)]) !!}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<small>Powered by {{ env('APP_NAME') }}</small>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -59,6 +59,14 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@if (UserModel::isCurrentlyAdmin())
|
||||
<div class="navbar-item">
|
||||
<a href="{{ url('/admin') }}">
|
||||
<i class="fas fa-cog" title="{{ __('app.admin_area') }}"></i><span class="navbar-item-only-mobile"> {{ __('app.admin_area') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="navbar-item">
|
||||
<a href="{{ url('/logout') }}">
|
||||
<i class="fas fa-sign-out-alt" title="{{ __('app.logout') }}"></i><span class="navbar-item-only-mobile"> {{ __('app.logout') }}</span>
|
||||
|
||||
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user