From 3e3ab32b80626859258d421be28b3e7a1eb1f6b8 Mon Sep 17 00:00:00 2001 From: Xinecraft Date: Tue, 12 Sep 2023 10:23:12 +0530 Subject: [PATCH 1/8] fix: :sparkles: Ability to change max size of profile and cover image via .env --- .env.example | 3 ++ .../Fortify/UpdateUserProfileInformation.php | 6 ++-- config/auth.php | 29 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 1b5d4603b..3670495c7 100644 --- a/.env.example +++ b/.env.example @@ -128,3 +128,6 @@ POWERED_BY_EXTRA_LINK= PING_PROXY_SERVER_USING_IP_ADDRESS=false QUERY_PROXY_SERVER_USING_IP_ADDRESS=true + +MAX_USER_PROFILE_PHOTO_SIZE_KB=512 +MAX_USER_COVER_PHOTO_SIZE_KB=1024 diff --git a/app/Actions/Fortify/UpdateUserProfileInformation.php b/app/Actions/Fortify/UpdateUserProfileInformation.php index 6089a0687..cc8f07704 100644 --- a/app/Actions/Fortify/UpdateUserProfileInformation.php +++ b/app/Actions/Fortify/UpdateUserProfileInformation.php @@ -16,11 +16,13 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation */ public function update($user, array $input) { + $maxProfilePhotoSize = config('auth.max_profile_photo_size_kb'); + $maxCoverPhotoSize = config('auth.max_cover_photo_size_kb'); Validator::make($input, [ 'name' => ['required', 'string', 'max:255'], // 'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)], - 'photo' => ['nullable', 'image', 'max:512'], - 'cover_image' => ['nullable', 'image', 'max:1024'], + 'photo' => ['nullable', 'image', 'max:' . $maxProfilePhotoSize], + 'cover_image' => ['nullable', 'image', 'max:' . $maxCoverPhotoSize], 'dob' => ['nullable', 'date', 'before:today'], 'gender' => ['nullable', 'in:m,f,o'], 'about' => ['nullable', 'string', 'max:255'], diff --git a/config/auth.php b/config/auth.php index 8aee57ee6..f6f70f3a8 100644 --- a/config/auth.php +++ b/config/auth.php @@ -119,6 +119,15 @@ 'password_timeout' => 10800, + /* + |-------------------------------------------------------------------------- + | Show Random Avatar for User + |-------------------------------------------------------------------------- + | + | If enabled, This feature will show random avatar/profile photo for users + | who don't have set any profile picture yet. + | + */ 'random_user_avatars' => env('RANDOM_USER_AVATARS', true), @@ -132,4 +141,24 @@ | */ 'any_provider_social_auth' => env('ALLOW_ANY_PROVIDER_SOCIAL_AUTH', false), + + /* + |-------------------------------------------------------------------------- + | Max Profile Photo Size (KB) + |-------------------------------------------------------------------------- + | + | Maximum allowed size for profile photo in kilobytes. + | + */ + 'max_profile_photo_size_kb' => env('MAX_USER_PROFILE_PHOTO_SIZE_KB', 512), + + /* + |-------------------------------------------------------------------------- + | Max Profile Cover Photo Size (KB) + |-------------------------------------------------------------------------- + | + | Maximum allowed size for user's cover photo in kilobytes. + | + */ + 'max_cover_photo_size_kb' => env('MAX_USER_COVER_PHOTO_SIZE_KB', 1024), ]; From dfaf2d7062190632830fdf272258984642e042e1 Mon Sep 17 00:00:00 2001 From: Xinecraft Date: Tue, 12 Sep 2023 18:11:54 +0530 Subject: [PATCH 2/8] fix: :zap: revamp staff members page a bit --- app/Http/Controllers/UserController.php | 20 ++-- database/factories/UserFactory.php | 3 + resources/js/Pages/User/IndexStaff.vue | 143 +++++++++++++----------- 3 files changed, 91 insertions(+), 75 deletions(-) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index cd2ea95bd..d595e7b0b 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -2,9 +2,7 @@ namespace App\Http\Controllers; -use App\Models\Role; use App\Models\User; -use Illuminate\Http\Request; use Inertia\Inertia; class UserController extends Controller @@ -15,20 +13,24 @@ public function showProfile(User $user): \Inertia\Response ->makeHidden(['email', 'dob', 'gender', 'updated_at', 'provider_id', 'provider_name', 'two_factor_confirmed_at', 'settings']); return Inertia::render('User/ShowUser', [ - 'profileUser' => $user->load('badges:id,name,shortname,sort_order') + 'profileUser' => $user->load('badges:id,name,shortname,sort_order'), ]); } public function indexStaff(): \Inertia\Response { - $rolesWithUsers = Role::with('users:id,name,username,profile_photo_path,verified_at') - ->where('is_hidden_from_staff_list', false) - ->orderByDesc('weight') - ->select(['id', 'name', 'display_name', 'is_staff', 'color']) - ->where('is_staff', true)->get(); + $staffsWithRole = User::with(['roles' => function ($query) { + $query->where('is_hidden_from_staff_list', false) + ->orderByDesc('weight'); + }]) + ->whereHas('roles', function ($query) { + $query->where('is_staff', true); + }) + ->select(['id', 'name', 'username', 'profile_photo_path', 'verified_at']) + ->get(); return Inertia::render('User/IndexStaff', [ - 'rolesWithUsers' => $rolesWithUsers + 'staffs' => $staffsWithRole, ]); } } diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index fc5a43aa1..6db78ecb9 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -2,6 +2,7 @@ namespace Database\Factories; +use App\Models\Country; use App\Models\Role; use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; @@ -23,6 +24,7 @@ class UserFactory extends Factory */ public function definition() { + $countryId = Country::inRandomOrder()->first()->id; return [ 'name' => $this->faker->name, 'username' => $this->faker->userName, @@ -31,6 +33,7 @@ public function definition() 'user_setup_status' => 1, 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), + 'country_id' => $countryId, ]; } diff --git a/resources/js/Pages/User/IndexStaff.vue b/resources/js/Pages/User/IndexStaff.vue index e2d501744..b0c2985c0 100644 --- a/resources/js/Pages/User/IndexStaff.vue +++ b/resources/js/Pages/User/IndexStaff.vue @@ -1,69 +1,98 @@ + + - - From 96f325c572bd38f32a8c9ff3ac2397d1db673e8a Mon Sep 17 00:00:00 2001 From: Xinecraft Date: Sun, 17 Sep 2023 12:33:31 +0530 Subject: [PATCH 3/8] Download APIs init --- .env.example | 1 + .../Controllers/Admin/DownloadController.php | 138 ++++++++++ app/Http/Controllers/DownloadController.php | 53 ++++ app/Http/Requests/CreateDownloadRequest.php | 32 +++ app/Http/Requests/UpdateDownloadRequest.php | 32 +++ app/Models/Download.php | 37 +++ app/Policies/DownloadPolicy.php | 75 ++++++ app/Providers/AuthServiceProvider.php | 3 +- config/filesystems.php | 7 +- config/minetrax.php | 36 ++- database/factories/DownloadFactory.php | 34 +++ ...23_09_12_132341_create_downloads_table.php | 43 +++ database/seeders/PermissionSeeder.php | 5 + resources/css/app.css | 10 + resources/js/Components/Form/XCheckbox.vue | 9 +- .../Pages/Admin/Download/CreateDownload.vue | 252 ++++++++++++++++++ .../js/Pages/Admin/Download/EditDownload.vue | 247 +++++++++++++++++ .../js/Pages/Admin/Download/IndexDownload.vue | 241 +++++++++++++++++ resources/js/Shared/AdminSideMenu.vue | 9 + routes/web.php | 12 + 20 files changed, 1258 insertions(+), 18 deletions(-) create mode 100644 app/Http/Controllers/Admin/DownloadController.php create mode 100644 app/Http/Controllers/DownloadController.php create mode 100644 app/Http/Requests/CreateDownloadRequest.php create mode 100644 app/Http/Requests/UpdateDownloadRequest.php create mode 100644 app/Models/Download.php create mode 100644 app/Policies/DownloadPolicy.php create mode 100644 database/factories/DownloadFactory.php create mode 100644 database/migrations/2023_09_12_132341_create_downloads_table.php create mode 100644 resources/js/Pages/Admin/Download/CreateDownload.vue create mode 100644 resources/js/Pages/Admin/Download/EditDownload.vue create mode 100644 resources/js/Pages/Admin/Download/IndexDownload.vue diff --git a/.env.example b/.env.example index 3670495c7..8c3e874fb 100644 --- a/.env.example +++ b/.env.example @@ -21,6 +21,7 @@ DB_PASSWORD=password FILESYSTEM_DISK=local MEDIA_DISK=media PROFILE_PHOTO_DISK=public +DOWNLOADS_MODULE_DISK=download BROADCAST_DRIVER=null CACHE_DRIVER=redis diff --git a/app/Http/Controllers/Admin/DownloadController.php b/app/Http/Controllers/Admin/DownloadController.php new file mode 100644 index 000000000..c2f0c64f2 --- /dev/null +++ b/app/Http/Controllers/Admin/DownloadController.php @@ -0,0 +1,138 @@ +authorize('viewAny', Download::class); + + $perPage = request()->input('perPage', 10); + if ($perPage > 100) { + $perPage = 100; + } + + $fields = [ + 'id', + 'name', + 'slug', + 'description', + 'is_external', + 'is_external_url_hidden', + 'is_only_auth', + 'is_active', + 'file_name', + 'file_url', + 'min_role_weight_required', + 'download_count', + 'created_at', + 'updated_at', + ]; + + $downloads = QueryBuilder::for(Download::class) + ->select($fields) + ->with('media') + ->allowedFilters([ + ...$fields, + AllowedFilter::custom('q', new FilterMultipleFields(['id', 'name', 'description', 'file_name'])), + ]) + ->allowedSorts($fields) + ->defaultSort('-id') + ->paginate($perPage) + ->through(function ($download) { + return $download->append('file')->makeHidden('media'); + }) + ->withQueryString(); + + return Inertia::render('Admin/Download/IndexDownload', [ + 'downloads' => $downloads, + 'filters' => request()->all(['perPage', 'sort', 'filter']), + ]); + } + + public function create(): \Inertia\Response + { + $this->authorize('create', Download::class); + + return Inertia::render('Admin/Download/CreateDownload'); + } + + public function store(CreateDownloadRequest $request) + { + $isExternal = $request->is_external; + if ($isExternal) { + $fileUrl = $request->file_url; + } + + $download = Download::create([ + 'name' => $request->name, + 'slug' => \Str::slug($request->name), + 'description' => $request->description, + 'is_external' => $request->is_external, + 'is_external_url_hidden' => $request->is_external_url_hidden, + 'file_url' => $fileUrl ?? null, + 'file_name' => $request->file_name ?? null, + 'is_only_auth' => $request->is_only_auth, + 'min_role_weight_required' => $request->min_role_weight_required, + 'is_active' => $request->is_active, + 'created_by' => $request->user()->id, + ]); + + // Upload the File if !isExternal + if (! $isExternal && $request->hasFile('file')) { + $download->addMediaFromRequest('file')->toMediaCollection('download'); + } + + return redirect()->route('admin.download.index') + ->with(['toast' => ['type' => 'success', 'title' => __('Created Successfully'), 'body' => __('Download has been created successfully')]]); + } + + public function edit(Download $download): \Inertia\Response + { + $this->authorize('update', Download::class); + + return Inertia::render('Admin/Download/EditDownload', [ + 'download' => $download->append('file')->makeHidden('media'), + ]); + } + + public function update(UpdateDownloadRequest $request, Download $download) + { + $this->authorize('update', $download); + + $download->update([ + 'name' => $request->name, + 'slug' => \Str::slug($request->name), + 'description' => $request->description, + 'is_external_url_hidden' => $request->is_external_url_hidden, + 'file_name' => $request->file_name ?? null, + 'is_only_auth' => $request->is_only_auth, + 'min_role_weight_required' => $request->min_role_weight_required, + 'is_active' => $request->is_active, + 'updated_by' => $request->user()->id, + ]); + + return redirect()->route('admin.download.index') + ->with(['toast' => ['type' => 'success', 'title' => __('Updated Successfully'), 'body' => __('Download has been updated successfully')]]); + } + + public function destroy(Download $download) + { + $this->authorize('delete', $download); + + $download->delete(); + + return redirect()->route('admin.download.index') + ->with(['toast' => ['type' => 'success', 'title' => __('Deleted Successfully'), 'body' => __('Download has been deleted permanently')]]); + } +} diff --git a/app/Http/Controllers/DownloadController.php b/app/Http/Controllers/DownloadController.php new file mode 100644 index 000000000..0bfd13d1c --- /dev/null +++ b/app/Http/Controllers/DownloadController.php @@ -0,0 +1,53 @@ +user() ? true : false; + + return Inertia::render('Download/IndexDownload', [ + 'downloads' => $downloads, + 'filters' => request()->all(['perPage', 'sort', 'filter']), + ]); + } + + public function show(Request $request, Download $download) + { + $this->authorize('download', $download); + + return Inertia::render('Download/ShowDownload', [ + 'download' => $download, + ]); + } + + public function download(Download $download) + { + $this->authorize('download', $download); + + $download->increment('download_count'); + + $isExternal = $download->is_external; + $isExternalUrlHidden = $download->is_external_url_hidden; + + if (! $isExternal) { + $file = $download->file; + + return $file; + } + + if ($isExternal && $isExternalUrlHidden) { + return response()->streamDownload(function () use ($download) { + echo file_get_contents($download->file_url); + }, $download->file_name); + } + + return redirect($download->file_url); + } +} diff --git a/app/Http/Requests/CreateDownloadRequest.php b/app/Http/Requests/CreateDownloadRequest.php new file mode 100644 index 000000000..e31a57fd3 --- /dev/null +++ b/app/Http/Requests/CreateDownloadRequest.php @@ -0,0 +1,32 @@ + 'required|string|max:255|unique:downloads', + 'description' => 'nullable|string', + 'is_external' => 'required|boolean', + 'file_url' => 'nullable|required_if:is_external,true|url', + 'file_name' => 'nullable|required_if:is_external,true|string|max:255', + 'is_external_url_hidden' => 'nullable|required_if:is_external,true|boolean', + 'is_only_auth' => 'required|boolean', + 'min_role_weight_required' => 'nullable|integer', + 'is_active' => 'required|boolean', + + 'file' => 'nullable|required_if:is_external,false|file|max:102400', //100mb + ]; + } +} diff --git a/app/Http/Requests/UpdateDownloadRequest.php b/app/Http/Requests/UpdateDownloadRequest.php new file mode 100644 index 000000000..6e26e9796 --- /dev/null +++ b/app/Http/Requests/UpdateDownloadRequest.php @@ -0,0 +1,32 @@ + [ + 'required', + 'string', + 'max:255', + Rule::unique('downloads')->ignore($this->route('download')), + ], + 'description' => 'nullable|string', + 'file_name' => 'nullable|required_if:is_external,true|string|max:255', + 'is_external_url_hidden' => 'nullable|required_if:is_external,true|boolean', + 'is_only_auth' => 'required|boolean', + 'min_role_weight_required' => 'nullable|integer', + 'is_active' => 'required|boolean', + ]; + } +} diff --git a/app/Models/Download.php b/app/Models/Download.php new file mode 100644 index 000000000..863da7df2 --- /dev/null +++ b/app/Models/Download.php @@ -0,0 +1,37 @@ + 'boolean', + 'is_external_url_hidden' => 'boolean', + 'is_only_auth' => 'boolean', + 'is_active' => 'boolean', + ]; + + public function registerMediaCollections(): void + { + $downloadsModuleDisk = config('minetrax.downloads_module_disk'); + $this->addMediaCollection('download') + ->useDisk($downloadsModuleDisk) + ->singleFile(); + } + + public function getFileAttribute() + { + $file = null; + if ($this->getFirstMedia('download')) { + $file = $this->getFirstMedia('download'); + } + + return $file; + } +} diff --git a/app/Policies/DownloadPolicy.php b/app/Policies/DownloadPolicy.php new file mode 100644 index 000000000..17cd007be --- /dev/null +++ b/app/Policies/DownloadPolicy.php @@ -0,0 +1,75 @@ +can('read downloads')) { + return true; + } + } + + public function view(User $user, Download $download) + { + if ($user->can('read downloads')) { + return true; + } + } + + public function create(User $user) + { + if ($user->can('create downloads')) { + return true; + } + } + + public function update(User $user, Download $download) + { + if ($user->can('update downloads')) { + return true; + } + } + + public function delete(User $user, Download $download) + { + if ($user->can('delete downloads')) { + return true; + } + } + + public function download(?User $user, Download $download) + { + // If admin, true + if ($user->can('read downloads')) { + return true; + } + + // If !is_active then false + if (! $download->is_active) { + return false; + } + + // If is_auth_only, then user should be authenticated + if ($download->is_auth_only && ! $user) { + return false; + } + + // if min_role_weight_required then check if user has role with weight >= min_role_weight_required + if ($download->is_auth_only && $download->min_role_weight_required) { + $userRoleWeight = $user->roles->max('weight'); + if ($userRoleWeight < $download->min_role_weight_required) { + return false; + } + } + + return true; + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 639379a76..b812dca41 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -20,13 +20,14 @@ class AuthServiceProvider extends ServiceProvider \App\Models\Shout::class => \App\Policies\ShoutPolicy::class, \App\Models\Comment::class => \App\Policies\CommentPolicy::class, \App\Models\Server::class => \App\Policies\ServerPolicy::class, - \App\Models\Role::class => \App\Policies\RolePolicy::class, + Role::class => \App\Policies\RolePolicy::class, \App\Models\Rank::class => \App\Policies\RankPolicy::class, \App\Models\News::class => \App\Policies\NewsPolicy::class, \App\Models\Poll::class => \App\Policies\PollPolicy::class, \App\Models\CustomPage::class => \App\Policies\CustomPagePolicy::class, \App\Models\Session::class => \App\Policies\SessionPolicy::class, \App\Models\Badge::class => \App\Policies\BadgePolicy::class, + \App\Models\Download::class => \App\Policies\DownloadPolicy::class, ]; /** diff --git a/config/filesystems.php b/config/filesystems.php index 337b3076c..3a357eebb 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -38,10 +38,15 @@ 'media' => [ 'driver' => 'local', - 'root' => storage_path('app/public/media'), + 'root' => storage_path('app/public/media'), 'url' => env('APP_URL').'/storage/media', ], + 'download' => [ + 'driver' => 'local', + 'root' => storage_path('app/downloads'), + ], + 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), diff --git a/config/minetrax.php b/config/minetrax.php index 908c241d5..1421872d3 100644 --- a/config/minetrax.php +++ b/config/minetrax.php @@ -9,7 +9,7 @@ | Hide powered by MineTrax references in footer and other places. | */ - "show_powered_by" => env("SHOW_POWERED_BY", true), + 'show_powered_by' => env('SHOW_POWERED_BY', true), /* |-------------------------------------------------------------------------- @@ -19,7 +19,7 @@ | hide or show the home button in navbar. | */ - "show_home_button" => env("SHOW_HOME_BUTTON", false), + 'show_home_button' => env('SHOW_HOME_BUTTON', false), /* |-------------------------------------------------------------------------- @@ -32,7 +32,7 @@ | Eg: Multicraft FTP Server, FileZilla FTP Server | */ - "use_legacy_ftp_driver" => env("USE_LEGACY_FTP_DRIVER", false), + 'use_legacy_ftp_driver' => env('USE_LEGACY_FTP_DRIVER', false), /* |-------------------------------------------------------------------------- @@ -44,7 +44,7 @@ | he removes linked player. | */ - "mark_user_verified_on_account_link" => env("MARK_USER_VERIFYED_ON_ACCOUNT_LINK", true), + 'mark_user_verified_on_account_link' => env('MARK_USER_VERIFYED_ON_ACCOUNT_LINK', true), /* |-------------------------------------------------------------------------- @@ -55,8 +55,7 @@ | services like minotar etc instead of uuid. | */ - "use_username_for_skins" => env("USE_USERNAME_FOR_SKINS", false), - + 'use_username_for_skins' => env('USE_USERNAME_FOR_SKINS', false), /* |-------------------------------------------------------------------------- @@ -71,10 +70,9 @@ | it might have unexpected behaviors. | */ - "players_fetcher_cron_interval" => env("PLAYER_FETCHER_CRON_INTERVAL", "hourly"), - - "fetch_avatar_from_url_using_curl" => env("FETCH_AVATAR_FROM_URL_USING_CURL", false), + 'players_fetcher_cron_interval' => env('PLAYER_FETCHER_CRON_INTERVAL', 'hourly'), + 'fetch_avatar_from_url_using_curl' => env('FETCH_AVATAR_FROM_URL_USING_CURL', false), /* |-------------------------------------------------------------------------- @@ -85,7 +83,7 @@ | Setting > Navigation | */ - "custom_nav_available_items_array" => [ + 'custom_nav_available_items_array' => [ [ 'type' => 'dropdown', 'name' => 'Dropdown', @@ -226,7 +224,7 @@ | If enabled, staff who have permission `use ask_db`, will be able to ask questions to database and get answers. | */ - "askdb_enabled" => env("ASKDB_ENABLED", false) && env("OPENAI_API_KEY"), + 'askdb_enabled' => env('ASKDB_ENABLED', false) && env('OPENAI_API_KEY'), /* |-------------------------------------------------------------------------- @@ -236,7 +234,7 @@ | If enabled, cookie consent will be shown to users for GDPR compliance. | */ - "cookie_consent_enabled" => env("COOKIE_CONSENT_ENABLED", true), + 'cookie_consent_enabled' => env('COOKIE_CONSENT_ENABLED', true), /* |-------------------------------------------------------------------------- @@ -247,8 +245,8 @@ | Helpful to show your name if you are a hosting provider or theme developer. | */ - "powered_by_extra_name" => env("POWERED_BY_EXTRA_NAME", null), - "powered_by_extra_link" => env("POWERED_BY_EXTRA_LINK", null), + 'powered_by_extra_name' => env('POWERED_BY_EXTRA_NAME', null), + 'powered_by_extra_link' => env('POWERED_BY_EXTRA_LINK', null), /* |-------------------------------------------------------------------------- @@ -262,4 +260,14 @@ */ 'ping_proxy_server_using_ip_address' => env('PING_PROXY_SERVER_USING_IP_ADDRESS', false), 'query_proxy_server_using_ip_address' => env('QUERY_PROXY_SERVER_USING_IP_ADDRESS', true), + + /* + |-------------------------------------------------------------------------- + | Downloads Module Disk + |-------------------------------------------------------------------------- + | + | Disk to use to store all files of Downloads Module. + | + */ + 'downloads_module_disk' => env('DOWNLOADS_MODULE_DISK', 'download'), ]; diff --git a/database/factories/DownloadFactory.php b/database/factories/DownloadFactory.php new file mode 100644 index 000000000..c25ad00d3 --- /dev/null +++ b/database/factories/DownloadFactory.php @@ -0,0 +1,34 @@ + + */ +class DownloadFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + 'name' => $this->faker->name, + 'description' => $this->faker->text, + 'is_external' => $this->faker->boolean, + 'is_exposed_external_url' => $this->faker->boolean, + 'is_only_auth' => $this->faker->boolean, + 'is_active' => $this->faker->boolean, + 'file_name' => $this->faker->userName(), + 'file_size' => $this->faker->randomNumber(), + 'file_path' => $this->faker->filePath(), + 'min_role_weight_required' => $this->faker->randomNumber(), + 'download_count' => $this->faker->randomNumber(), + ]; + } +} diff --git a/database/migrations/2023_09_12_132341_create_downloads_table.php b/database/migrations/2023_09_12_132341_create_downloads_table.php new file mode 100644 index 000000000..7b3c4ceee --- /dev/null +++ b/database/migrations/2023_09_12_132341_create_downloads_table.php @@ -0,0 +1,43 @@ +id(); + $table->string('name')->unique(); + $table->string('slug')->unique(); + $table->text('description')->nullable(); + $table->boolean('is_external')->default(false); // if external, then file_url is set. + $table->boolean('is_external_url_hidden')->default(false); // external only setting, if true minetrax download file and stream to user so url is not exposed. + $table->string('file_url')->nullable(); // if external, then file_path is url. + $table->string('file_name')->nullable(); + + $table->boolean('is_only_auth')->default(false); // only authenticated user. + $table->integer('min_role_weight_required')->nullable(); // if authenticated, min weight of role of user needed. + + $table->boolean('is_active')->default(true); + $table->bigInteger('download_count')->default(0); + + $table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null'); + $table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('downloads'); + } +}; diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php index 1ad74a4ba..79f1d6984 100644 --- a/database/seeders/PermissionSeeder.php +++ b/database/seeders/PermissionSeeder.php @@ -87,5 +87,10 @@ public function run() Permission::findOrCreate('view player_intel_critical'); // View critical player_intel which only admin should view, player ip, inventory data etc. Permission::findOrCreate('use ask_db'); + + Permission::findOrCreate('create downloads'); + Permission::findOrCreate('read downloads'); + Permission::findOrCreate('update downloads'); + Permission::findOrCreate('delete downloads'); } } diff --git a/resources/css/app.css b/resources/css/app.css index a4d453afe..7bcf7eec0 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -223,3 +223,13 @@ body.swal2-shown > [aria-hidden="true"] { .mx-datepicker-sidebar button { font-size: small; } + +.CodeMirror { + color: #8c8c8c; + border-color: #333; + background-color: inherit; +} + +.cm-s-easymde .CodeMirror-cursor { + border-color: #a0a0a0; +} diff --git a/resources/js/Components/Form/XCheckbox.vue b/resources/js/Components/Form/XCheckbox.vue index 2709aaf56..bcc67da24 100644 --- a/resources/js/Components/Form/XCheckbox.vue +++ b/resources/js/Components/Form/XCheckbox.vue @@ -4,9 +4,10 @@ :id="id" ref="input" v-model="proxyChecked" + :disabled="disabled" type="checkbox" :name="name" - class="rounded border-gray-300 dark:bg-cool-gray-900 dark:border-gray-900 text-light-blue-500 shadow-sm focus:border-light-blue-300 focus:ring focus:ring-light-blue-200 focus:ring-opacity-50" + class="rounded border-gray-300 dark:bg-cool-gray-900 dark:border-gray-900 text-light-blue-500 shadow-sm focus:border-light-blue-300 focus:ring focus:ring-light-blue-200 focus:ring-opacity-50 disabled:opacity-25 transition ease-in-out duration-150" :class="checkboxSizeClass" :required="required" @input="$emit('input', $event.target.value)" @@ -49,7 +50,11 @@ export default { required: { type: Boolean, default: false - } + }, + disabled: { + type: Boolean, + default: false + }, }, computed: { diff --git a/resources/js/Pages/Admin/Download/CreateDownload.vue b/resources/js/Pages/Admin/Download/CreateDownload.vue new file mode 100644 index 000000000..7eb451103 --- /dev/null +++ b/resources/js/Pages/Admin/Download/CreateDownload.vue @@ -0,0 +1,252 @@ +