diff --git a/app/Controllers/Auth/LoginController.php b/app/Controllers/Auth/LoginController.php index 7904daf..03b9003 100644 --- a/app/Controllers/Auth/LoginController.php +++ b/app/Controllers/Auth/LoginController.php @@ -51,7 +51,7 @@ class LoginController extends Controller } $username = param($request, 'username'); - $user = $this->database->query('SELECT `id`, `email`, `username`, `password`,`is_admin`, `active`, `current_disk_quota`, `max_disk_quota`, `ldap` FROM `users` WHERE `username` = ? OR `email` = ? LIMIT 1', [$username, $username])->fetch(); + $user = $this->database->query('SELECT `id`, `email`, `username`, `password`,`is_admin`, `active`, `current_disk_quota`, `max_disk_quota`, `ldap`, `copy_raw` FROM `users` WHERE `username` = ? OR `email` = ? LIMIT 1', [$username, $username])->fetch(); if ($this->config['ldap']['enabled'] && ($user->ldap ?? true)) { $user = $this->ldapLogin($request, $username, param($request, 'password'), $user); @@ -80,6 +80,7 @@ class LoginController extends Controller $this->session->set('user_id', $user->id); $this->session->set('username', $user->username); $this->session->set('admin', $user->is_admin); + $this->session->set('copy_raw', $user->copy_raw); $this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota); $this->session->alert(lang('welcome', [$user->username]), 'info'); diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 8bcff69..c668573 100644 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -73,7 +73,7 @@ class DashboardController extends Controller 'next' => $page < floor($query->getPages()), 'previous' => $page >= 1, 'current_page' => ++$page, - 'copy_url_behavior' => $this->getSetting('copy_url_behavior', 'off'), + 'copy_raw' => $this->session->get('copy_raw', false), 'tags' => $tags, ] ); diff --git a/app/Controllers/ExportController.php b/app/Controllers/ExportController.php index 39f568b..84093db 100644 --- a/app/Controllers/ExportController.php +++ b/app/Controllers/ExportController.php @@ -25,6 +25,8 @@ class ExportController extends Controller $medias = $this->database->query('SELECT `uploads`.`filename`, `uploads`.`storage_path` FROM `uploads` WHERE `user_id` = ?', $user->id); + $this->logger->info("User $user->id, $user->name, exporting data..."); + set_time_limit(0); ob_end_clean(); diff --git a/app/Controllers/ProfileController.php b/app/Controllers/ProfileController.php index 45807ec..9a69bcf 100644 --- a/app/Controllers/ProfileController.php +++ b/app/Controllers/ProfileController.php @@ -59,14 +59,18 @@ class ProfileController extends Controller } if (param($request, 'password') !== null && !empty(param($request, 'password'))) { - $this->database->query('UPDATE `users` SET `email`=?, `password`=? WHERE `id` = ?', [ + $this->database->query('UPDATE `users` SET `email`=?, `password`=?, `hide_uploads`=?, `copy_raw`=? WHERE `id` = ?', [ param($request, 'email'), password_hash(param($request, 'password'), PASSWORD_DEFAULT), + param($request, 'hide_uploads') !== null ? 1 : 0, + param($request, 'copy_raw') !== null ? 1 : 0, $user->id, ]); } else { - $this->database->query('UPDATE `users` SET `email`=? WHERE `id` = ?', [ + $this->database->query('UPDATE `users` SET `email`=?, `hide_uploads`=?, `copy_raw`=? WHERE `id` = ?', [ param($request, 'email'), + param($request, 'hide_uploads') !== null ? 1 : 0, + param($request, 'copy_raw') !== null ? 1 : 0, $user->id, ]); } diff --git a/app/Controllers/SettingController.php b/app/Controllers/SettingController.php index e98c1bd..16fded8 100644 --- a/app/Controllers/SettingController.php +++ b/app/Controllers/SettingController.php @@ -27,25 +27,24 @@ class SettingController extends Controller return redirect($response, route('system')); } + // registrations $this->updateSetting('register_enabled', param($request, 'register_enabled', 'off')); - $this->updateSetting('hide_by_default', param($request, 'hide_by_default', 'off')); - $this->updateSetting('quota_enabled', param($request, 'quota_enabled', 'off')); + // quota + $this->updateSetting('quota_enabled', param($request, 'quota_enabled', 'off')); + $this->updateSetting('default_user_quota', stringToBytes(param($request, 'default_user_quota', '1G'))); $user = make(UserQuery::class)->get($request, $this->session->get('user_id')); $this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota); - $this->updateSetting('default_user_quota', stringToBytes(param($request, 'default_user_quota', '1G'))); - $this->updateSetting('copy_url_behavior', param($request, 'copy_url_behavior') === null ? 'default' : 'raw'); - - $this->applyTheme($request); - $this->applyLang($request); $this->updateSetting('custom_head', param($request, 'custom_head')); - - $this->updateSetting('recaptcha_enabled', param($request, 'recaptcha_enabled', 'off')); $this->updateSetting('recaptcha_site_key', param($request, 'recaptcha_site_key')); $this->updateSetting('recaptcha_secret_key', param($request, 'recaptcha_secret_key')); + $this->applyTheme($request); + $this->applyLang($request); + + $this->logger->info("User $user->username updated the system settings."); $this->session->alert(lang('settings_saved')); return redirect($response, route('system')); diff --git a/app/Controllers/TagController.php b/app/Controllers/TagController.php index 8d50955..a95c1bd 100644 --- a/app/Controllers/TagController.php +++ b/app/Controllers/TagController.php @@ -30,6 +30,8 @@ class TagController extends Controller [$id, $limit] = make(TagQuery::class)->addTag(param($request, 'tag'), param($request, 'mediaId')); + $this->logger->info("Tag added $id."); + return json($response, [ 'limitReached' => $limit, 'tagId' => $id, @@ -58,6 +60,8 @@ class TagController extends Controller throw new HttpNotFoundException($request); } + $this->logger->info("Tag removed ".param($request, 'tagId').', from media '.param($request, 'mediaId')); + return $response; } diff --git a/app/Controllers/UpgradeController.php b/app/Controllers/UpgradeController.php index 91f338c..6e070aa 100644 --- a/app/Controllers/UpgradeController.php +++ b/app/Controllers/UpgradeController.php @@ -51,6 +51,7 @@ class UpgradeController extends Controller return redirect($response, route('system')); } + $this->logger->info('System update started.'); $config = require BASE_DIR.'config.php'; $config['maintenance'] = true; @@ -89,6 +90,8 @@ class UpgradeController extends Controller $updateZip->close(); unlink($tmpFile); + $this->logger->info('System update completed.'); + return redirect($response, urlFor('/install')); } diff --git a/app/Controllers/UploadController.php b/app/Controllers/UploadController.php index bad2562..1c75fef 100644 --- a/app/Controllers/UploadController.php +++ b/app/Controllers/UploadController.php @@ -30,7 +30,7 @@ class UploadController extends Controller $maxFileSize = min(stringToBytes(ini_get('post_max_size')), stringToBytes(ini_get('upload_max_filesize'))); return view()->render($response, 'upload/web.twig', [ - 'max_file_size' => humanFileSize($maxFileSize) + 'max_file_size' => humanFileSize($maxFileSize), ]); } @@ -42,12 +42,6 @@ class UploadController extends Controller */ public function uploadWeb(Request $request, Response $response): Response { - if ($this->config['maintenance']) { - $this->json['message'] = 'Endpoint under maintenance.'; - - return json($response, $this->json, 503); - } - try { $file = $this->validateFile($request, $response); @@ -92,25 +86,15 @@ class UploadController extends Controller try { $file = $this->validateFile($request, $response); - } catch (ValidationException $e) { - return $e->response(); - } - if (param($request, 'token') === null) { - $this->json['message'] = 'Token not specified.'; + if (param($request, 'token') === null) { + $this->json['message'] = 'Token not specified.'; - return json($response, $this->json, 400); - } + return json($response, $this->json, 400); + } - $user = $this->database->query('SELECT * FROM `users` WHERE `token` = ? LIMIT 1', param($request, 'token'))->fetch(); + $user = $this->database->query('SELECT * FROM `users` WHERE `token` = ? LIMIT 1', param($request, 'token'))->fetch(); - if (!$user) { - $this->json['message'] = 'Token specified not found.'; - - return json($response, $this->json, 404); - } - - try { $this->validateUser($request, $response, $file, $user); } catch (ValidationException $e) { return $e->response(); @@ -174,6 +158,12 @@ class UploadController extends Controller */ protected function validateUser(Request $request, Response $response, UploadedFileInterface $file, $user) { + if (!$user) { + $this->json['message'] = 'Token specified not found.'; + + throw new ValidationException(json($response, $this->json, 404)); + } + if (!$user->active) { $this->json['message'] = 'Account disabled.'; @@ -196,11 +186,6 @@ class UploadController extends Controller $code = humanRandomString(); } while ($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `code` = ?', $code)->fetch()->count > 0); - $published = 1; - if ($this->getSetting('hide_by_default') === 'on') { - $published = 0; - } - $fileInfo = pathinfo($file->getClientFilename()); $storagePath = "$user->user_code/$code.$fileInfo[extension]"; @@ -211,7 +196,7 @@ class UploadController extends Controller $code, $file->getClientFilename(), $storagePath, - $published, + $user->hide_uploads == '1' ? 0 : 1, ]); $mediaId = $this->database->getPdo()->lastInsertId(); diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php index 8b78a39..ef1d198 100644 --- a/app/Controllers/UserController.php +++ b/app/Controllers/UserController.php @@ -95,7 +95,10 @@ class UserController extends Controller param($request, 'password'), param($request, 'is_admin') !== null ? 1 : 0, param($request, 'is_active') !== null ? 1 : 0, - $maxUserQuota + $maxUserQuota, + false, + param($request, 'hide_uploads') !== null ? 1 : 0, + param($request, 'copy_raw') !== null ? 1 : 0 ); if (param($request, 'send_notification') !== null) { @@ -186,7 +189,9 @@ class UserController extends Controller param($request, 'is_admin') !== null ? 1 : 0, param($request, 'is_active') !== null ? 1 : 0, $user->max_disk_quota, - param($request, 'ldap') !== null ? 1 : 0 + param($request, 'ldap') !== null ? 1 : 0, + param($request, 'hide_uploads') !== null ? 1 : 0, + param($request, 'copy_raw') !== null ? 1 : 0 ); if ($user->id === $this->session->get('user_id')) { diff --git a/app/Database/Queries/UserQuery.php b/app/Database/Queries/UserQuery.php index a53f488..36d9190 100644 --- a/app/Database/Queries/UserQuery.php +++ b/app/Database/Queries/UserQuery.php @@ -70,7 +70,6 @@ class UserQuery return $user; } - /** * @param string $email * @param string $username @@ -80,9 +79,11 @@ class UserQuery * @param int $maxUserQuota * @param string|null $activateToken * @param int $ldap + * @param int $hideUploads + * @param int $copyRaw * @return bool|\PDOStatement|string */ - public function create(string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, string $activateToken = null, int $ldap =0) + public function create(string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, string $activateToken = null, int $ldap = 0, int $hideUploads = 0, int $copyRaw = 0) { do { $userCode = humanRandomString(5); @@ -90,7 +91,7 @@ class UserQuery $token = $this->generateUserUploadToken(); - return $this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `max_disk_quota`, `activate_token`, `ldap`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ + return $this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `max_disk_quota`, `activate_token`, `ldap`, `hide_uploads`, `copy_raw`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ $email, $username, $password !== null ? password_hash($password, PASSWORD_DEFAULT) : null, @@ -100,7 +101,9 @@ class UserQuery $token, $maxUserQuota, $activateToken, - $ldap + $ldap, + $hideUploads, + $copyRaw, ]); } @@ -113,12 +116,14 @@ class UserQuery * @param int $isActive * @param int $maxUserQuota * @param int $ldap + * @param int $hideUploads + * @param int $copyRaw * @return bool|\PDOStatement|string */ - public function update($id, string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, int $ldap = 0) + public function update($id, string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, int $ldap = 0, int $hideUploads = 0, int $copyRaw = 0) { if (!empty($password)) { - return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=? WHERE `id` = ?', [ + return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=?, `hide_uploads`=?, `copy_raw`=? WHERE `id` = ?', [ $email, $username, password_hash($password, PASSWORD_DEFAULT), @@ -126,16 +131,20 @@ class UserQuery $isActive, $maxUserQuota, $ldap, + $hideUploads, + $copyRaw, $id, ]); } else { - return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=? WHERE `id` = ?', [ + return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=?, `hide_uploads`=?, `copy_raw`=? WHERE `id` = ?', [ $email, $username, $isAdmin, $isActive, $maxUserQuota, $ldap, + $hideUploads, + $copyRaw, $id, ]); } diff --git a/docs/basic_usage.md b/docs/basic_usage.md index f73be2e..55865c6 100644 --- a/docs/basic_usage.md +++ b/docs/basic_usage.md @@ -16,6 +16,8 @@ Some functions that every user that use XBackBone should know: + (`v3.1`+) With the right click on the uploaded media, you can select them, and then remove them in bulk. + (`v3.1`+) You can add additional tag to your uploads, clicking on the **+** button on the media. + (`v3.1`+) You can add you can delete tags, by right-click on them. ++ (`v3.1`+) You can choose in your profile options if hide the uploads by default. ++ (`v3.1`+) You can choose in your profile options if always copy the raw url (from the web interface). ## Administrator In addition, from the system page, and administrator can: diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..59474da --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,195 @@ +--- +layout: default +title: Changelog +nav_order: 8 +--- + +## v.3.1 (WIP) ++ Added tagging system (add, delete, search of tagged files). ++ Added basic media auto-tagging on upload. ++ Added registration system. ++ Added password recovery system. ++ Added ability to export all media of an account. ++ Added ability to choose between default and raw url on copy. ++ Added hide by default option. ++ Added user disk quota. ++ Added reCAPTCHA login protection. ++ Added bulk delete. ++ Added account clean function. ++ Added user disk quota system. ++ Added notification option on account create. ++ Added LDAP authentication. ++ Fixed bug html files raws are rendered in a browser. ++ The theme is now re-applied after every system update. ++ Updated system settings page. ++ Updated translations. ++ Improved grid layout. ++ Fixes and improvements. + +## v.3.0.2 ++ Fixed error with migrate command. ++ Updated translations. + +## v.3.0.1 ++ Fixed error with older mysql versions. ++ Fixed config is compiled with the di container. ++ Small installer update. + +## v.3.0 ++ Upgraded from Slim3 to Slim 4. ++ Added web upload. ++ Added ability to add custom HTML in \
tag. ++ Added ability to show a preview of PDF files. ++ Added remember me functionality. ++ Added delete button on the preview page if the user is logged in. ++ New project icon (by [@SerenaItalia](https://www.deviantart.com/serenaitalia)). ++ Raw URL now accept file extensions. ++ The linux script can be used on headless systems. ++ Improved installer. ++ Improved thumbnail generation. ++ Replaced videojs player with Plyr. ++ Implemented SameSite XSS protection. ++ Small fixes and improvements. + +## v.2.6.6 ++ Ability to choose between releases and prereleases with the web updater. ++ Updated translations. + +## v2.6.5 ++ Fixed error after orphaned files removal #74. ++ Fixed update password not correctly removed from log files #74. ++ Changed color to some buttons to address visibility with some themes. + +## v2.6.4 ++ Filter on displayable images. ++ Fixed during upload error on php compiled for 32 bit. ++ Fixed icons on the installer page. ++ The generated random strings are now more human readable. + +## v2.6.3 ++ Fixed #67. ++ Fixed bad preload statement. ++ Fixed wrong redirect after install in subdirs. + +## v2.6.2 ++ Use the font awesome web font for better performances. ++ Changed background default color. ++ Added method for cache busting when updating/change theme. ++ Added russian translation from [Weblate](https://hosted.weblate.org/projects/xbackbone/xbackbone/). + +## v2.6.1 ++ Fixed bad redirects on the web installer (#62). ++ Fixed login page with dark themes. ++ Improved shell commands. ++ Added alert if required extensions are not loaded. ++ Updated translations. + +## v2.6 ++ Added support to use AWS S3, Google Cloud Storage, Dropbox and FTP(s) accounts as storage location. ++ Fixed missing icon. ++ Added german and norwegian translations from [Weblate](https://hosted.weblate.org/projects/xbackbone/xbackbone/). ++ Improved lang detection. ++ Added ability to force system language. + +## v2.5.3 ++ Fixed bad css loading on Firefox (#35). ++ Fixed wrong style for publish/unpublish button. ++ Improved exception stacktrace logging. + +## v2.5.2 ++ Improved session handling. ++ Fixed telegram share not working. ++ Fix for big text file now are not rendered in the browser. ++ Added preloading for some resources to improve performances. ++ Added check for block execution on EOL and unsupported PHP versions. ++ Other minor improvements. + +## v2.5.1 ++ Fixed bad redirect if the theme folder is not writable. (#27) ++ Improved HTTP partial content implementation for large files. + +## v2.5 ++ Updated project license to AGPL v3.0 (now releases ships with the new license). ++ **[BETA]** Added self update feature. ++ Added partial content implementation (stream seeking on chromium based browsers). ++ Improved video.js alignment with large videos. ++ Optimized output zip release size. ++ Templates cleanup and optimizations. ++ Improved error handling. ++ Added project favicon. + +## v2.4.1 ++ Fixed error message when the file is too large. (#15) ++ Fixed button alignment. + +## v2.4 ++ Added function to remove orphaned files. ++ Switch between tab and gallery mode using an admin account. ++ Multiple uploads sorting methods. ++ Search in uploads. ++ Internal refactoring and improvements ++ Updated js dependencies. + +## v2.3.1 ++ Fixed en lang. ++ Fixed forced background with dark themes. ++ Added checks during the installation wizard. ++ cURL and Wget can now directly download the file. + +## v2.3 ++ Improved image scaling in user gallery. ++ Added overlay on user gallery images. ++ Fixed IT translation. ++ Fontawesome icon match the single file mime-type. ++ Enable audio player with video.js. ++ Video and audio now starts with volume at 50%. ++ Added linux script to allow uploads from linux screenshot tools. ++ Minor layout fixes. + +## v2.2 ++ Added multi-language support. ++ Improved routing. ++ Fixed HTTP/2 push is resetting the current session. ++ Minor improvements and bug fixes. + +## v2.1 ++ Improved theme style. ++ Improved page redirecting. ++ Allow e-mail login. ++ Support for ShareX deletion URL. ++ Fixed HTTP/2 push preload. ++ Added video.js support. + +## v2.0 ++ Migrated from Flight to Slim 3 framework. ++ Added install wizard (using the CLI is no longer required). ++ Allow discord bot to display the preview. ++ Theme switcher on the web UI. ++ Added used space indicator per user. ++ MySQL support. ++ Improvements under the hood. + +## v1.3 ++ Added command to switch between bootswatch.com themes. ++ Added popever to write the telegram message when sharing. ++ Packaging improvements. ++ Updated some dependencies. ++ Allow Facebook bots to display the preview. + +## v1.2 ++ Previews are now scaled for better page load. ++ Added auto config generator for ShareX. ++ Show upload file size on the dashboard. ++ Fixed insert for admin user (running `php bin\migrate --install`). ++ Removed HTTP2 push from the dashboard to improve loading time. + +## v1.1 ++ Added logging. ++ Fixed back to top when click delete or publish/unpublish. ++ Improved migrate system. ++ Login redirect back to the requested page. ++ Updated Bootstrap theme. ++ Added share to Telegram. + +## v1.0 ++ Initial version. diff --git a/docs/common_issues.md b/docs/common_issues.md index eb622da..129eb61 100644 --- a/docs/common_issues.md +++ b/docs/common_issues.md @@ -6,11 +6,11 @@ nav_order: 7 # Common Issues -#### Error 404 after installation +### Error 404 after installation If you have apache, check if it's reading the file `.htaccess` and the `mod_rewrite` is enabled. -#### [Discord, Telegram, ...] is not showing the image/video preview of the link. +### [Discord, Telegram, ...] is not showing the image/video preview of the link. If you have Cloudflare enabled, check if it's blocking bots. If this function is enabled the Discord bot, Telebot, etc that fetch the preview will be blocked. -#### How to increase the max file size? +### How to increase the max file size? Increase the post_max_size and upload_max_filesize in your php.ini \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 0c23008..edb60af 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,11 +11,12 @@ nav_order: 1 XBackBone is a simple and lightweight PHP file manager that support the instant sharing tool ShareX and *NIX systems. It supports uploading and displaying images, GIF, video, code, formatted text, pdf, and file downloading and uploading. Also have a web UI with multi user management, media gallery and search support. {: .fs-5 .fw-300 } +[Download](https://github.com/SergiX44/XBackBone/releases/latest){: .btn .btn-green } [GitHub](https://github.com/SergiX44/XBackBone){: .btn .btn-blue } +
## Main Features - + Supports every upload type from ShareX. + Config generator for ShareX. + Low memory footprint. diff --git a/docs/license.md b/docs/license.md index 7cb8062..db7994d 100644 --- a/docs/license.md +++ b/docs/license.md @@ -1,7 +1,7 @@ --- layout: default title: License & Credits -nav_order: 8 +nav_order: 9 --- # License diff --git a/resources/schemas/mysql/mysql.7.sql b/resources/schemas/mysql/mysql.7.sql index 6c9cc08..3a95791 100644 --- a/resources/schemas/mysql/mysql.7.sql +++ b/resources/schemas/mysql/mysql.7.sql @@ -1 +1,3 @@ -ALTER TABLE `users` ADD COLUMN `ldap` BOOLEAN NOT NULL DEFAULT 0; \ No newline at end of file +ALTER TABLE `users` ADD COLUMN `ldap` BOOLEAN NOT NULL DEFAULT 0; +ALTER TABLE `users` ADD COLUMN `hide_uploads` BOOLEAN NOT NULL DEFAULT 0; +ALTER TABLE `users` ADD COLUMN `copy_raw` BOOLEAN NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/resources/schemas/sqlite/sqlite.7.sql b/resources/schemas/sqlite/sqlite.7.sql index 6c9cc08..3a95791 100644 --- a/resources/schemas/sqlite/sqlite.7.sql +++ b/resources/schemas/sqlite/sqlite.7.sql @@ -1 +1,3 @@ -ALTER TABLE `users` ADD COLUMN `ldap` BOOLEAN NOT NULL DEFAULT 0; \ No newline at end of file +ALTER TABLE `users` ADD COLUMN `ldap` BOOLEAN NOT NULL DEFAULT 0; +ALTER TABLE `users` ADD COLUMN `hide_uploads` BOOLEAN NOT NULL DEFAULT 0; +ALTER TABLE `users` ADD COLUMN `copy_raw` BOOLEAN NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/resources/templates/dashboard/grid.twig b/resources/templates/dashboard/grid.twig index 4f4f979..2ac058a 100644 --- a/resources/templates/dashboard/grid.twig +++ b/resources/templates/dashboard/grid.twig @@ -19,7 +19,7 @@