├── .nvmrc ├── database ├── .gitignore ├── seeders │ ├── DatabaseSeeder.php │ ├── PermissionTableSeeder.php │ └── ConnectRelationshipsSeeder.php ├── migrations │ ├── 2014_10_00_000001_add_group_column_on_settings_table.php │ ├── 2022_09_30_181227_create_categories_table.php │ ├── 2025_01_23_093056_add_event_column_to_activity_log_table.php │ ├── 2025_01_23_093057_add_batch_uuid_column_to_activity_log_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2022_09_30_181156_create_posts_table.php │ ├── 2014_10_00_000000_create_settings_table.php │ ├── 2023_10_02_010617_create_category_post_table.php │ ├── 0001_01_01_000001_create_cache_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ ├── 2022_12_06_061947_create_impersonations_table.php │ ├── 2025_01_23_093055_create_activity_log_table.php │ ├── 2022_11_28_073632_create_socialite_providers_table.php │ ├── 2023_10_02_175025_create_media_table.php │ ├── 2016_01_15_105324_create_roles_table.php │ ├── 2016_01_26_115212_create_permissions_table.php │ ├── 2016_01_15_114412_create_role_user_table.php │ ├── 2016_01_26_115523_create_permission_role_table.php │ └── 2016_02_09_132439_create_permission_user_table.php └── factories │ └── UserFactory.php ├── bootstrap └── cache │ └── .gitignore ├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore └── framework │ ├── testing │ └── .gitignore │ ├── views │ └── .gitignore │ ├── cache │ ├── data │ │ └── .gitignore │ └── .gitignore │ ├── sessions │ └── .gitignore │ └── .gitignore ├── public ├── robots.txt ├── favicon.ico ├── favicon.png ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── images │ └── placeholder.jpg ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── sw.js ├── site.webmanifest ├── .htaccess └── serviceworker.js ├── resources ├── img │ ├── 404.png │ ├── login.png │ ├── login.webp │ ├── plugs.png │ ├── favicon │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ └── site.webmanifest │ ├── vendor-logos │ │ ├── vultr-1.webp │ │ ├── vultr-2.png │ │ ├── zoho-monocrome-black.png │ │ └── zoho-monocrome-white.png │ └── fonts │ │ ├── Nunito │ │ ├── static │ │ │ ├── Nunito-Bold.ttf │ │ │ ├── Nunito-Black.ttf │ │ │ ├── Nunito-Italic.ttf │ │ │ ├── Nunito-Light.ttf │ │ │ ├── Nunito-Medium.ttf │ │ │ ├── Nunito-ExtraBold.ttf │ │ │ ├── Nunito-Regular.ttf │ │ │ ├── Nunito-SemiBold.ttf │ │ │ ├── Nunito-BlackItalic.ttf │ │ │ ├── Nunito-BoldItalic.ttf │ │ │ ├── Nunito-ExtraLight.ttf │ │ │ ├── Nunito-LightItalic.ttf │ │ │ ├── Nunito-MediumItalic.ttf │ │ │ ├── Nunito-SemiBoldItalic.ttf │ │ │ ├── Nunito-ExtraBoldItalic.ttf │ │ │ └── Nunito-ExtraLightItalic.ttf │ │ ├── Nunito-VariableFont_wght.ttf │ │ └── Nunito-Italic-VariableFont_wght.ttf │ │ ├── Leckerli_One │ │ └── LeckerliOne-Regular.ttf │ │ └── Quicksand │ │ ├── static │ │ ├── Quicksand-Bold.ttf │ │ ├── Quicksand-Light.ttf │ │ ├── Quicksand-Medium.ttf │ │ ├── Quicksand-Regular.ttf │ │ └── Quicksand-SemiBold.ttf │ │ └── Quicksand-VariableFont_wght.ttf ├── js │ ├── lang │ │ ├── bn.json │ │ ├── zh-CN.json │ │ ├── es.json │ │ └── pt-BR.json │ ├── views │ │ ├── auth │ │ │ ├── Verify.vue │ │ │ └── passwords │ │ │ │ └── ConfirmPage.vue │ │ ├── templates │ │ │ ├── Bare.vue │ │ │ └── Blank.vue │ │ ├── pages │ │ │ └── user-settings │ │ │ │ ├── AccountData.vue │ │ │ │ └── SettingsNavLink.vue │ │ └── posts │ │ │ └── PublicIndex.vue │ ├── services │ │ ├── ability.js │ │ └── analytics.js │ ├── components │ │ ├── common │ │ │ ├── LoadingCircle.vue │ │ │ ├── UmoEditor.vue │ │ │ ├── AppTable.vue │ │ │ ├── SuccessNotice.vue │ │ │ ├── TextEditorComponent.vue │ │ │ ├── SocialMediaLoginStatusItem.vue │ │ │ ├── AdminMiniCard.vue │ │ │ ├── CircleSvg.vue │ │ │ ├── AppSwitch.vue │ │ │ ├── PerPage.vue │ │ │ ├── CKEditorComponent.vue │ │ │ └── NoRecordsCTA.vue │ │ ├── admin │ │ │ ├── EditComp.vue │ │ │ └── IndexComp.vue │ │ ├── includes │ │ │ ├── AdminBreadcrumbContainer.vue │ │ │ ├── AdminBreadcrumbSep.vue │ │ │ ├── BreadcrumbOld.vue │ │ │ ├── AdminBreadcrumb.vue │ │ │ ├── AppFooter.vue │ │ │ ├── NavLink.vue │ │ │ └── AdminNavBarLink.vue │ │ ├── users │ │ │ └── UserForm.vue │ │ ├── form │ │ │ ├── AppSettingTextInput.vue │ │ │ ├── AppSettingTextarea.vue │ │ │ └── AppSettingToggle.vue │ │ ├── LocaleSwitcher.vue │ │ ├── roles │ │ │ └── RolesBadges.vue │ │ └── plugs │ │ │ ├── GHButton.vue │ │ │ ├── VultrReferral.vue │ │ │ └── PatreonButton.vue │ ├── store │ │ ├── index.js │ │ ├── sidebar.js │ │ └── lang.js │ ├── routes │ │ └── index.js │ ├── validation │ │ └── rules.js │ ├── layouts │ │ ├── ErrorLayout.vue │ │ ├── AuthenticatedLayout.vue │ │ └── GuestLayout.vue │ ├── plugins │ │ └── i18n.js │ └── bootstrap.js ├── pwa │ ├── sw.js │ └── serviceworker.js └── views │ ├── socialite │ ├── denied.blade.php │ └── callback.blade.php │ ├── home.blade.php │ └── auth │ └── verify.blade.php ├── vue.config.js ├── config ├── browser-sessions.php ├── laravel-https.php ├── cors.php ├── users.php ├── personal-data-export.php ├── view.php ├── laravel-page-speed.php ├── sitemap.php └── hashing.php ├── .prettierrc.json ├── app ├── Models │ ├── Role.php │ ├── Setting.php │ ├── CategoryPost.php │ ├── Permission.php │ ├── Category.php │ └── Impersonation.php ├── Http │ ├── Middleware │ │ ├── EncryptCookies.php │ │ ├── VerifyCsrfToken.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── TrustHosts.php │ │ ├── TrimStrings.php │ │ ├── Authenticate.php │ │ ├── ValidateSignature.php │ │ ├── TrustProxies.php │ │ └── RedirectIfAuthenticated.php │ ├── Requests │ │ ├── Posts │ │ │ ├── ShowPostRequest.php │ │ │ ├── DeletePostRequest.php │ │ │ ├── RestorePostRequest.php │ │ │ ├── StorePostRequest.php │ │ │ └── UpdatePostRequest.php │ │ ├── Users │ │ │ ├── LeaveImpersonateUserRequest.php │ │ │ ├── VerifyUserRequest.php │ │ │ ├── ViewUserRequest.php │ │ │ ├── DeleteUserRequest.php │ │ │ ├── RestoreUserRequest.php │ │ │ ├── ImpersonateUserRequest.php │ │ │ ├── CreateUserRequest.php │ │ │ └── UpdateUserRequest.php │ │ ├── Roles │ │ │ ├── GetUserRolesRequest.php │ │ │ ├── CreateRoleRequest.php │ │ │ └── UpdateRoleRequest.php │ │ ├── StoreRoleRequest.php │ │ ├── Categories │ │ │ ├── StoreCategoryRequest.php │ │ │ ├── ShowCategoryRequest.php │ │ │ ├── DeleteCategoryRequest.php │ │ │ ├── RestoreCategoryRequest.php │ │ │ └── UpdateCategoryRequest.php │ │ ├── Permissions │ │ │ ├── GetPermissionsRequest.php │ │ │ ├── CreatePermissionRequest.php │ │ │ └── UpdatePermissionRequest.php │ │ ├── UpdateProfileRequest.php │ │ ├── Admin │ │ │ ├── AdminDashboardRequest.php │ │ │ ├── ShowServerInfoRequest.php │ │ │ ├── ShowAppSettingsRequest.php │ │ │ └── UpdateAppSettingsRequest.php │ │ ├── Auth │ │ │ └── RegisterRequest.php │ │ └── StoreUserRequest.php │ ├── Controllers │ │ ├── Api │ │ │ ├── BrowserSessionController.php │ │ │ ├── ActivityLogController.php │ │ │ └── ProfileController.php │ │ ├── HomeController.php │ │ ├── Auth │ │ │ ├── PasswordController.php │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ └── ConfirmPasswordController.php │ │ ├── Admin │ │ │ ├── ServerInfoController.php │ │ │ ├── DashboardController.php │ │ │ └── AppSettingsController.php │ │ └── Controller.php │ └── Resources │ │ ├── Categories │ │ ├── CategoryResource.php │ │ └── GategoriesCollection.php │ │ ├── Roles │ │ ├── RoleResource.php │ │ └── RolesCollection.php │ │ ├── Permissions │ │ ├── PermissionResource.php │ │ └── PermissionsCollection.php │ │ ├── Posts │ │ ├── PostsCollection.php │ │ └── PostResource.php │ │ ├── Users │ │ ├── UsersCollection.php │ │ └── UserResource.php │ │ └── ActivityLogs │ │ ├── ActivityLogsCollection.php │ │ └── ActivityLogResource.php ├── Exceptions │ └── SocialProviderDeniedException.php ├── Providers │ ├── BroadcastServiceProvider.php │ ├── AppServiceProvider.php │ ├── ViewComposerServiceProvider.php │ ├── AuthServiceProvider.php │ └── RouteServiceProvider.php ├── Jobs │ └── PersonalDataExportJob.php ├── View │ └── Composers │ │ ├── GaComposer.php │ │ └── GaEnabledComposer.php ├── Services │ └── AppleToken.php ├── Notifications │ ├── VerifyEmailNotification.php │ └── ResetPasswordNotification.php └── Console │ └── Kernel.php ├── prettier.config.js ├── postcss.config.js ├── tests ├── TestCase.php ├── Unit │ └── ExampleTest.php ├── Feature │ └── ExampleTest.php └── CreatesApplication.php ├── .eslintrc.json ├── .gitattributes ├── SECURITY.md ├── lang ├── vendor │ └── personal-data-export │ │ └── en │ │ └── notifications.php └── en │ ├── pagination.php │ ├── auth.php │ └── passwords.php ├── .prettierignore ├── routes ├── channels.php ├── console.php └── web.php ├── .editorconfig ├── .gitignore ├── eslint.config.js ├── LICENSE ├── phpunit.xml ├── tailwind.config.js ├── .eslintrc.js └── .scripts └── deploy.sh /.nvmrc: -------------------------------------------------------------------------------- 1 | 24 -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/favicon.png -------------------------------------------------------------------------------- /resources/img/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/404.png -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /resources/img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/login.png -------------------------------------------------------------------------------- /resources/img/login.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/login.webp -------------------------------------------------------------------------------- /resources/img/plugs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/plugs.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/images/placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/images/placeholder.jpg -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /resources/img/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/favicon.ico -------------------------------------------------------------------------------- /resources/img/favicon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/favicon.png -------------------------------------------------------------------------------- /resources/img/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /resources/img/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /resources/img/vendor-logos/vultr-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/vendor-logos/vultr-1.webp -------------------------------------------------------------------------------- /resources/img/vendor-logos/vultr-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/vendor-logos/vultr-2.png -------------------------------------------------------------------------------- /resources/img/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /resources/js/lang/bn.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome_starter_title": "Laravel Vue 3 Starter-এ স্বাগতম", 3 | "ok": "Ok", 4 | "cancel": "Cancel" 5 | } 6 | -------------------------------------------------------------------------------- /resources/img/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /resources/img/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-Bold.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-Black.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-Italic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-Light.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-Medium.ttf -------------------------------------------------------------------------------- /resources/img/vendor-logos/zoho-monocrome-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/vendor-logos/zoho-monocrome-black.png -------------------------------------------------------------------------------- /resources/img/vendor-logos/zoho-monocrome-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/vendor-logos/zoho-monocrome-white.png -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-ExtraBold.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-Regular.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-SemiBold.ttf -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Delete the prefetch plugin 3 | chainWebpack: (config) => { 4 | config.plugins.delete('prefetch'); 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /resources/img/fonts/Leckerli_One/LeckerliOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Leckerli_One/LeckerliOne-Regular.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/Nunito-VariableFont_wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/Nunito-VariableFont_wght.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-BlackItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-BoldItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-ExtraLight.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-LightItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Quicksand/static/Quicksand-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Quicksand/static/Quicksand-Bold.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Quicksand/static/Quicksand-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Quicksand/static/Quicksand-Light.ttf -------------------------------------------------------------------------------- /config/browser-sessions.php: -------------------------------------------------------------------------------- 1 | true, 5 | 'browser_session_guard' => env('BROWSER_SESSION_GUARD', 'web'), 6 | ]; 7 | -------------------------------------------------------------------------------- /public/sw.js: -------------------------------------------------------------------------------- 1 | import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching'; 2 | 3 | cleanupOutdatedCaches(); 4 | 5 | precacheAndRoute(self.__WB_MANIFEST); 6 | -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-MediumItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Quicksand/static/Quicksand-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Quicksand/static/Quicksand-Medium.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Quicksand/static/Quicksand-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Quicksand/static/Quicksand-Regular.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Quicksand/static/Quicksand-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Quicksand/static/Quicksand-SemiBold.ttf -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 120, 7 | "bracketSpacing": true 8 | } 9 | -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/static/Nunito-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/static/Nunito-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /resources/img/fonts/Quicksand/Quicksand-VariableFont_wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Quicksand/Quicksand-VariableFont_wght.ttf -------------------------------------------------------------------------------- /resources/js/views/auth/Verify.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /resources/pwa/sw.js: -------------------------------------------------------------------------------- 1 | import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching'; 2 | 3 | cleanupOutdatedCaches(); 4 | 5 | precacheAndRoute(self.__WB_MANIFEST); 6 | -------------------------------------------------------------------------------- /resources/img/fonts/Nunito/Nunito-Italic-VariableFont_wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremykenedy/laravel-spa/HEAD/resources/img/fonts/Nunito/Nunito-Italic-VariableFont_wght.ttf -------------------------------------------------------------------------------- /resources/js/views/templates/Bare.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | compiled.php 2 | config.php 3 | down 4 | events.scanned.php 5 | maintenance.php 6 | routes.php 7 | routes.scanned.php 8 | schedule-* 9 | services.json 10 | -------------------------------------------------------------------------------- /app/Models/Role.php: -------------------------------------------------------------------------------- 1 | 2 |

Confirm

3 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | // prettier.config.js or .prettierrc.js 2 | module.exports = { 3 | trailingComma: 'all', 4 | tabWidth: 2, 5 | semi: true, 6 | singleQuote: true, 7 | bracketSpacing: true, 8 | }; 9 | -------------------------------------------------------------------------------- /resources/views/socialite/denied.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors.layout') 2 | 3 | @section('title', 'Login Error') 4 | 5 | @section('message', 'You did not share your profile data with '.config('app.name').'.') 6 | -------------------------------------------------------------------------------- /resources/js/services/ability.js: -------------------------------------------------------------------------------- 1 | import { AbilityBuilder, createMongoAbility } from '@casl/ability'; 2 | 3 | const { can, cannot, build } = new AbilityBuilder(createMongoAbility); 4 | 5 | export default build(); 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | 'postcss-import': {}, 6 | 'tailwindcss/nesting': {}, 7 | 'postcss-nesting': {}, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.blade.php diff=html 4 | *.css diff=css 5 | *.html diff=html 6 | *.md diff=markdown 7 | *.php diff=php 8 | 9 | /.github export-ignore 10 | CHANGELOG.md export-ignore 11 | .styleci.yml export-ignore 12 | -------------------------------------------------------------------------------- /app/Models/CategoryPost.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
Admin Edit
6 |
7 |
8 |
9 | 10 | -------------------------------------------------------------------------------- /resources/js/components/common/UmoEditor.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | -------------------------------------------------------------------------------- /resources/js/store/index.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export default defineStore({ 4 | state: { 5 | // 6 | }, 7 | mutations: { 8 | // 9 | }, 10 | actions: { 11 | // 12 | }, 13 | modules: { 14 | // 15 | }, 16 | plugins: [ 17 | // 18 | ], 19 | }); 20 | -------------------------------------------------------------------------------- /app/Models/Permission.php: -------------------------------------------------------------------------------- 1 | 'Personal Data Download', 5 | 'instructions' => 'Please click the button below to download a zip file containing all data we got for your account.', 6 | 'action' => 'Download Zip File', 7 | 'deletion_message' => 'This file will be deleted at :date.', 8 | ]; 9 | -------------------------------------------------------------------------------- /tests/Unit/ExampleTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/js/components/includes/AdminBreadcrumbContainer.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /node_modules 3 | dist/ 4 | .prettierrc.js 5 | .eslintrc.js 6 | .eslintrc.cjs 7 | env.d.ts 8 | .env 9 | vendor/ 10 | /vendor 11 | public/ 12 | .git 13 | **/.git 14 | **/.svn 15 | **/.hg 16 | **/node_modules 17 | package-lock.json 18 | package.json 19 | composer.json 20 | composer.lock 21 | docker-compose.yml 22 | README.md 23 | /.devcontainer 24 | #prettierrc.js 25 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Requests/Posts/ShowPostRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('view.articles'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Requests/Posts/DeletePostRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('delete.articles'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/LeaveImpersonateUserRequest.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |

Admin

8 |
9 |
10 |
11 |
12 |
13 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'api/*', 'login', 'register', 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/VerifyUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('edit.users'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/ViewUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('view.users'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /resources/js/components/includes/AdminBreadcrumbSep.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /app/Http/Requests/Roles/GetUserRolesRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('view.roles'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/DeleteUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('delete.users'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/RestoreUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('restore.users'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/img/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/ImpersonateUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('impersonate.users'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventRequestsDuringMaintenance.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustHosts.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function hosts() 15 | { 16 | return [ 17 | $this->allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'current_password', 16 | 'password', 17 | 'password_confirmation', 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 18 | 19 | $response->assertStatus(200); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Exceptions/SocialProviderDeniedException.php: -------------------------------------------------------------------------------- 1 | view('socialite.denied', [], 401); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | env('LARAVEL_FORCEHTTPSCHECKENVIRONMENT', true), 11 | 'ForceHttpsEnvironmentToCheck' => env('LARAVEL_FORCEHTTPSENVIRONMENTTOCHECK', 'production'), 12 | 'httpsAccessDeniedErrorCode' => env('LARAVEL_HTTP_ERROR_CODE', 403), 13 | 14 | ]; 15 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/BrowserSessionController.php: -------------------------------------------------------------------------------- 1 | json($sessions); 15 | } 16 | 17 | public function logoutOtherDevices() 18 | { 19 | return BrowserSessions::logoutOtherBrowserSessions(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 15 | } 16 | 17 | /** 18 | * Show the application dashboard. 19 | * 20 | * @return \Illuminate\Contracts\Support\Renderable 21 | */ 22 | public function index() 23 | { 24 | return view('home'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return route('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/ValidateSignature.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 'fbclid', 16 | // 'utm_campaign', 17 | // 'utm_content', 18 | // 'utm_medium', 19 | // 'utm_source', 20 | // 'utm_term', 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /resources/views/socialite/callback.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ config('app.name') }} 8 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/js/routes/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router'; 2 | import routes from './routes.js'; 3 | 4 | const router = createRouter({ 5 | history: createWebHistory(), 6 | routes, 7 | }); 8 | 9 | /*router.beforeEach((to, from, next) => { 10 | 11 | if (store.getters.user) { 12 | if (to.matched.some(route => route.meta.guard === 'guest')) next({ name: 'home' }) 13 | else next(); 14 | 15 | } else { 16 | if (to.matched.some(route => route.meta.guard === 'auth')) next({ name: 'login' }) 17 | else next(); 18 | } 19 | })*/ 20 | 21 | export default router; 22 | -------------------------------------------------------------------------------- /lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /resources/js/validation/rules.js: -------------------------------------------------------------------------------- 1 | const required = (value, args, { field }) => { 2 | if (!value) { 3 | return `The ${field} field is required.`; 4 | } 5 | 6 | return true; 7 | }; 8 | 9 | const email = (value, args, { field }) => { 10 | if (!value) { 11 | return `The ${field} field is required.`; 12 | } 13 | 14 | return true; 15 | }; 16 | 17 | const min = (value, [limit], { field }) => { 18 | if (!value || !value.length) { 19 | return true; 20 | } 21 | 22 | if (value.length < limit) { 23 | return `The ${field} must be at least ${limit} characters.`; 24 | } 25 | 26 | return true; 27 | }; 28 | 29 | export { required, min, email }; 30 | -------------------------------------------------------------------------------- /resources/js/store/sidebar.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export const useSideBarStore = defineStore('sidebar', { 4 | namespaced: true, 5 | state: () => ({ 6 | sideBarOpen: false, 7 | fullScreenSideBarOpen: true, 8 | }), 9 | getters: { 10 | sideBarOpenGetter: (state) => state.sideBarOpen, 11 | fullScreenSideBarOpenGetter: (state) => state.fullScreenSideBarOpen, 12 | }, 13 | actions: { 14 | toggleSidebar() { 15 | this.sideBarOpen = !this.sideBarOpen; 16 | }, 17 | toggleFullScreenSidebar() { 18 | this.fullScreenSideBarOpen = !this.fullScreenSideBarOpen; 19 | }, 20 | }, 21 | persist: true, 22 | }); 23 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /app/Http/Requests/StoreRoleRequest.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(PermissionsTableSeeder::class); 18 | $this->call(RolesTableSeeder::class); 19 | $this->call(ConnectRelationshipsSeeder::class); 20 | $this->call(UsersTableSeeder::class); 21 | $this->call(AppSettingsSeeder::class); 22 | 23 | Model::reguard(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/js/components/common/AppTable.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | user(); 14 | $request->validate([ 15 | 'password' => 'required|min:6|max:255|confirmed', 16 | ]); 17 | $user->update(['password' => Hash::make($request->password)]); 18 | 19 | return response()->json([ 20 | 'message' => 'Password Updated Successfully', 21 | ], 200); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Requests/Categories/StoreCategoryRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('create.categories'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array 21 | */ 22 | public function rules() 23 | { 24 | return [ 25 | 'name' => 'required', 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Requests/Permissions/GetPermissionsRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('view.permissions'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | // 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/Posts/RestorePostRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('restore.articles'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | // 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'password' => 'The provided password is incorrect.', 18 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /database/migrations/2014_10_00_000001_add_group_column_on_settings_table.php: -------------------------------------------------------------------------------- 1 | dropUnique('settings_name_unique'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('settings', function (Blueprint $table) { 25 | // 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Dashboard') }}
9 | 10 |
11 | @if (session('status')) 12 | 15 | @endif 16 | 17 | {{ __('You are logged in!') }} 18 |
19 |
20 |
21 |
22 |
23 | @endsection 24 | -------------------------------------------------------------------------------- /app/Http/Requests/Categories/ShowCategoryRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('view.categories'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | // 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.php] 12 | charset = utf-8 13 | end_of_line = lf 14 | insert_final_newline = true 15 | indent_style = space 16 | indent_size = 4 17 | trim_trailing_whitespace = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | 22 | [*.{yml,yaml}] 23 | indent_size = 2 24 | 25 | [docker-compose.yml] 26 | indent_size = 4 27 | 28 | [*.js] 29 | indent_style = space 30 | indent_size = 2 31 | 32 | [*.ts] 33 | indent_style = space 34 | indent_size = 2 35 | 36 | [*.json] 37 | indent_style = space 38 | indent_size = 2 39 | 40 | [*.vue] 41 | indent_style = space 42 | indent_size = 2 43 | -------------------------------------------------------------------------------- /app/Http/Requests/Categories/DeleteCategoryRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('delete.categories'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | // 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Requests/Categories/RestoreCategoryRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('restore.categories'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | // 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateProfileRequest.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|min:5', 28 | 'email' => 'required|email|unique:users,email,'.$this->user()->id, 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /resources/js/components/common/SuccessNotice.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 30 | -------------------------------------------------------------------------------- /app/Http/Resources/Categories/CategoryResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'posts' => $this->posts, 21 | 'created_at' => $this->created_at, 22 | 'updated_at' => $this->created_at, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | |string|null 14 | */ 15 | protected $proxies; 16 | 17 | /** 18 | * The headers that should be used to detect proxies. 19 | * 20 | * @var int 21 | */ 22 | protected $headers = 23 | Request::HEADER_X_FORWARDED_FOR | 24 | Request::HEADER_X_FORWARDED_HOST | 25 | Request::HEADER_X_FORWARDED_PORT | 26 | Request::HEADER_X_FORWARDED_PROTO | 27 | Request::HEADER_X_FORWARDED_AWS_ELB; 28 | } 29 | -------------------------------------------------------------------------------- /app/Providers/ViewComposerServiceProvider.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'value' => $this->id, 21 | 'created_at' => $this->created_at->toDateString(), 22 | 'updated_at' => $this->created_at->toDateString(), 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### OSX Vendor Configs ### 2 | .DS_Store 3 | *._DS_Store 4 | ._.DS_Store 5 | *._ 6 | ._* 7 | ._.* 8 | 9 | ### Windows Vendor Configs ### 10 | Thumbs.db 11 | 12 | ### Editor Configs ### 13 | *.sublime-workspace 14 | .idea/* 15 | /.idea/* 16 | .phpintel/* 17 | /.phpintel/* 18 | /.vscode 19 | /.notes/* 20 | 21 | ### Assets ### 22 | /node_modules 23 | /public/build 24 | /public/hot 25 | /public/storage 26 | /storage/*.key 27 | /vendor 28 | .env 29 | .env.backup 30 | .phpunit.result.cache 31 | Homestead.json 32 | Homestead.yaml 33 | auth.json 34 | npm-debug.log 35 | yarn-error.log 36 | /storage/debugbar 37 | /storage/framework/cache/* 38 | /storage/framework/sessions/* 39 | /storage/framework/testing/* 40 | /storage/framework/views/* 41 | docker-compose.override.yml 42 | composer.lock 43 | npm-bundle-stats.html 44 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/AdminDashboardRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasRole('superadmin'); 15 | // return $this->user()->hasPermission('super.admin'); 16 | } 17 | 18 | /** 19 | * Get the validation rules that apply to the request. 20 | * 21 | * @return array|string> 22 | */ 23 | public function rules(): array 24 | { 25 | return [ 26 | // 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/ShowServerInfoRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasRole('superadmin'); 15 | // return $this->user()->hasPermission('super.admin'); 16 | } 17 | 18 | /** 19 | * Get the validation rules that apply to the request. 20 | * 21 | * @return array|string> 22 | */ 23 | public function rules(): array 24 | { 25 | return [ 26 | // 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/ShowAppSettingsRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasRole('superadmin'); 15 | // return $this->user()->hasPermission('super.admin'); 16 | } 17 | 18 | /** 19 | * Get the validation rules that apply to the request. 20 | * 21 | * @return array|string> 22 | */ 23 | public function rules(): array 24 | { 25 | return [ 26 | // 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/View/Composers/GaComposer.php: -------------------------------------------------------------------------------- 1 | key = Setting::where('key', 'appGoogleAnalyticsKey')->first(); 20 | } 21 | 22 | /** 23 | * Bind data to the view. 24 | * 25 | * @param \Illuminate\View\View $view 26 | * @return void 27 | */ 28 | public function compose(View $view) 29 | { 30 | $val = null; 31 | 32 | if ($this->key) { 33 | $val = $this->key->val; 34 | } 35 | 36 | $view->with('ga_key', $val); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/js/components/common/TextEditorComponent.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/UpdateAppSettingsRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasRole('superadmin'); 15 | // return $this->user()->hasPermission('super.admin'); 16 | } 17 | 18 | /** 19 | * Get the validation rules that apply to the request. 20 | * 21 | * @return array|string> 22 | */ 23 | public function rules(): array 24 | { 25 | return [ 26 | // 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Resources/Permissions/PermissionResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'value' => $this->id, 21 | 'created_at' => $this->created_at->toDateString(), 22 | 'updated_at' => $this->created_at->toDateString(), 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/migrations/2022_09_30_181227_create_categories_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name')->unique(); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('categories'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/ServerInfoController.php: -------------------------------------------------------------------------------- 1 | (.*).*$%ms', '$1', $pinfo); 26 | 27 | return response()->json([ 28 | 'info' => $pinfo, 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/View/Composers/GaEnabledComposer.php: -------------------------------------------------------------------------------- 1 | key = Setting::where('key', 'enableGoogleAnalytics')->first(); 20 | } 21 | 22 | /** 23 | * Bind data to the view. 24 | * 25 | * @param \Illuminate\View\View $view 26 | * @return void 27 | */ 28 | public function compose(View $view) 29 | { 30 | $val = null; 31 | 32 | if ($this->key) { 33 | $val = $this->key->val; 34 | } 35 | 36 | $view->with('ga_enabled', $val); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2025_01_23_093056_add_event_column_to_activity_log_table.php: -------------------------------------------------------------------------------- 1 | table(config('activitylog.table_name'), function (Blueprint $table) { 12 | $table->string('event')->nullable()->after('subject_type'); 13 | }); 14 | } 15 | 16 | public function down(): void 17 | { 18 | Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) { 19 | $table->dropColumn('event'); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Posts/StorePostRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('create.articles'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules() 23 | { 24 | return [ 25 | 'title' => 'required', 26 | 'content' => 'required', 27 | 'categories' => 'required', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/Posts/UpdatePostRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('edit.articles'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules() 23 | { 24 | return [ 25 | 'title' => 'required', 26 | 'content' => 'required', 27 | 'categories' => 'required', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2025_01_23_093057_add_batch_uuid_column_to_activity_log_table.php: -------------------------------------------------------------------------------- 1 | table(config('activitylog.table_name'), function (Blueprint $table) { 12 | $table->uuid('batch_uuid')->nullable()->after('properties'); 13 | }); 14 | } 15 | 16 | public function down(): void 17 | { 18 | Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) { 19 | $table->dropColumn('batch_uuid'); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /app/Models/Category.php: -------------------------------------------------------------------------------- 1 | logOnly(['name', 'text']); 23 | // Chain fluent methods for configuration options 24 | } 25 | 26 | /** 27 | * Get the posts for the category. 28 | */ 29 | public function posts() 30 | { 31 | return $this->belongsToMany(Post::class, 'category_post'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have emailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /app/Http/Requests/Auth/RegisterRequest.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => ['required', 'string', 'max:255'], 28 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 29 | 'password' => ['required', 'string', 'min:8', 'confirmed'], 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Requests/Categories/UpdateCategoryRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('edit.categories'); 15 | } 16 | 17 | /** 18 | * Get the validation rules that apply to the request. 19 | * 20 | * @return array|string> 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | 'name' => 'required|max:255', 26 | // 'name' => 'required|string|max:255|unique:categories,name,'.$category->id, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Requests/StoreUserRequest.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | 'name' => ['required', 'string', 'max:255'], 26 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 27 | 'password' => ['required', 'string', 'min:8'], 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2022_09_30_181156_create_posts_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('title'); 19 | $table->unsignedBigInteger('user_id'); 20 | $table->longText('content'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down(): void 31 | { 32 | Schema::dropIfExists('posts'); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | name('dashboard') 25 | ->where('any', '.*'); 26 | -------------------------------------------------------------------------------- /app/Services/AppleToken.php: -------------------------------------------------------------------------------- 1 | jwtConfig = $jwtConfig; 15 | } 16 | 17 | public function generate() 18 | { 19 | $now = CarbonImmutable::now(); 20 | 21 | $token = $this->jwtConfig->builder() 22 | ->issuedBy(config('services.apple.team_id')) 23 | ->issuedAt($now) 24 | ->expiresAt($now->addHour()) 25 | ->permittedFor('https://appleid.apple.com') 26 | ->relatedTo(config('services.apple.client_id')) 27 | ->withHeader('kid', config('services.apple.key_id')) 28 | ->getToken($this->jwtConfig->signer(), $this->jwtConfig->signingKey()); 29 | 30 | return $token->toString(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/js/components/users/UserForm.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /database/migrations/2014_10_00_000000_create_settings_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('key')->unique(); 17 | $table->string('name')->unique(); 18 | $table->string('type')->default('string'); 19 | $table->longtext('val')->nullable(); 20 | $table->string('group')->default('default'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('settings'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /app/Http/Resources/Posts/PostsCollection.php: -------------------------------------------------------------------------------- 1 | collection->map(function ($value) { 32 | return new PostResource($value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Resources/Roles/RolesCollection.php: -------------------------------------------------------------------------------- 1 | collection->map(function ($value) { 32 | return new RoleResource($value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Resources/Users/UsersCollection.php: -------------------------------------------------------------------------------- 1 | collection->map(function ($value) { 32 | return new UserResource($value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*', 'sanctum/csrf-cookie'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | json([ 19 | 'success' => true, 20 | 'message' => $message, 21 | 'data' => $data, 22 | ], $code); 23 | } 24 | 25 | protected function errorResponse($message = null, $code) 26 | { 27 | return response()->json([ 28 | 'success' => false, 29 | 'message' => $message, 30 | 'data' => null, 31 | ], $code); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Notifications/VerifyEmailNotification.php: -------------------------------------------------------------------------------- 1 | addMinutes(60), 26 | [ 27 | 'id' => $notifiable->getKey(), 28 | 'hash' => sha1($notifiable->getEmailForVerification()), 29 | ] 30 | ); 31 | 32 | return str_replace('/api', '', $url); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'eslint/config'; 2 | import pluginVue from 'eslint-plugin-vue'; 3 | 4 | export default defineConfig([ 5 | ...pluginVue.configs['flat/recommended'], 6 | { 7 | files: ['resources/js/**/*.js'], 8 | languageOptions: { 9 | ecmaVersion: 2021, 10 | sourceType: 'module', 11 | }, 12 | rules: { 13 | semi: ['error', 'always'], 14 | 'prefer-const': 'warn', 15 | 'no-unused-vars': 'warn', 16 | 'vue/multi-word-component-names': 'warn', 17 | 'vue/require-v-for-key': 'warn', 18 | 'vue/one-component-per-file': 'warn', 19 | 'vue/no-reserved-component-names': 'warn', 20 | 'vue/no-unused-vars': 0, 21 | 'vue/html-self-closing': 0, 22 | '@typescript-eslint/no-empty-function': 0, 23 | 'no-useless-catch': 0, 24 | '@typescript-eslint/no-unused-vars': 0, 25 | 'vue/no-unused-components': 0, 26 | 'vue/require-explicit-emits': 0, 27 | 'no-undef': 0, 28 | }, 29 | }, 30 | ]); 31 | -------------------------------------------------------------------------------- /app/Http/Resources/Categories/GategoriesCollection.php: -------------------------------------------------------------------------------- 1 | collection->map(function ($value) { 32 | return new CategoryResource($value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Resources/Permissions/PermissionsCollection.php: -------------------------------------------------------------------------------- 1 | collection->map(function ($value) { 32 | return new PermissionResource($value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/js/components/common/SocialMediaLoginStatusItem.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 37 | -------------------------------------------------------------------------------- /app/Http/Requests/Roles/CreateRoleRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('create.roles'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string|min:3|max:255', 28 | 'slug' => 'required|string|unique:roles,slug', 29 | 'description' => 'nullable|string|max:255', 30 | 'level' => 'nullable|integer', 31 | 'permissions' => 'present|array', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Resources/ActivityLogs/ActivityLogsCollection.php: -------------------------------------------------------------------------------- 1 | collection->map(function ($value) { 32 | return new ActivityLogResource($value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 19 | ]; 20 | 21 | /** 22 | * Register any authentication / authorization services. 23 | * 24 | * @return void 25 | */ 26 | public function boot() 27 | { 28 | $this->registerPolicies(); 29 | 30 | $this->app->bind(Configuration::class, fn () => Configuration::forSymmetricSigner( 31 | Sha256::create(), 32 | InMemory::plainText(config('services.apple.private_key')), 33 | )); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2023_10_02_010617_create_category_post_table.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('category_id'); 16 | $table->unsignedBigInteger('post_id'); 17 | $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade'); 18 | $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade'); 19 | $table->primary(['category_id', 'post_id']); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down(): void 27 | { 28 | Schema::dropIfExists('category_post'); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /app/Http/Requests/Roles/UpdateRoleRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('edit.roles'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string|min:3|max:255', 28 | // 'slug' => 'required|string|unique:roles,slug,'.$role->id, 29 | 'description' => 'nullable|string|max:255', 30 | 'level' => 'nullable|integer', 31 | 'permissions' => 'present|array', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Resources/Users/UserResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'name' => $this->name, 20 | 'email' => $this->email, 21 | 'role_id' => $this->roles, 22 | 'roles' => $this->roles, 23 | 'permissions' => $this->permissions, 24 | 'created_at' => $this->created_at->toDateString(), 25 | 'updated_at' => $this->created_at->toDateString(), 26 | 'deleted_at' => $this->created_at->toDateString(), 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/js/store/lang.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie'; 2 | import { defineStore } from 'pinia'; 3 | import { ref } from 'vue'; 4 | 5 | export const useLangStore = defineStore( 6 | 'lang', 7 | () => { 8 | const { locale, locales } = window.config; 9 | const langLocale = ref(getLocale(locales, locale)); 10 | const langLocales = locales; 11 | 12 | const setLocale = (newLocale) => { 13 | langLocale.value = newLocale; 14 | Cookies.set('locale', newLocale, { expires: 365 }); 15 | }; 16 | 17 | return { langLocale, langLocales, setLocale }; 18 | }, 19 | { 20 | persist: true, 21 | }, 22 | ); 23 | 24 | /** 25 | * @param {String[]} locales 26 | * @param {String} fallback 27 | * @return {String} 28 | */ 29 | function getLocale(locales, fallback) { 30 | const locale = Cookies.get('locale'); 31 | 32 | if (Object.prototype.hasOwnProperty.call(locales, locale)) { 33 | return locale; 34 | } else if (locale) { 35 | Cookies.remove('locale'); 36 | } 37 | 38 | return fallback; 39 | } 40 | -------------------------------------------------------------------------------- /resources/js/views/pages/user-settings/AccountData.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 32 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 26 | return redirect(RouteServiceProvider::HOME); 27 | } 28 | } 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/0001_01_01_000001_create_cache_table.php: -------------------------------------------------------------------------------- 1 | string('key')->primary(); 16 | $table->mediumText('value'); 17 | $table->integer('expiration'); 18 | }); 19 | 20 | Schema::create('cache_locks', function (Blueprint $table) { 21 | $table->string('key')->primary(); 22 | $table->string('owner'); 23 | $table->integer('expiration'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | */ 30 | public function down(): void 31 | { 32 | Schema::dropIfExists('cache'); 33 | Schema::dropIfExists('cache_locks'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /resources/js/lang/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome_starter_title": "欢迎来到Laravel Vue 3入门版", 3 | "ok": "确定", 4 | "cancel": "取消", 5 | "error_alert_title": "错误...", 6 | "error_alert_text": "遇到一些错误,请稍后重试~", 7 | "token_expired_alert_title": "验证过期!", 8 | "token_expired_alert_text": "请稍后重新登录系统", 9 | "login": "登录", 10 | "register": "注册", 11 | "page_not_found": "页面不存在", 12 | "go_home": "返回首页", 13 | "logout": "退出", 14 | "email": "邮箱", 15 | "remember_me": "记住我", 16 | "password": "密码", 17 | "forgot_password": "忘记密码?", 18 | "confirm_password": "重复密码", 19 | "name": "用户名", 20 | "toggle_navigation": "切换导航", 21 | "home": "首页", 22 | "you_are_logged_in": "您已经登录!", 23 | "reset_password": "重置密码", 24 | "send_password_reset_link": "发送重置链接", 25 | "settings": "设置", 26 | "profile": "个人设置", 27 | "your_info": "您的个人信息", 28 | "info_updated": "您的个人信息已经更改!", 29 | "update": "更新", 30 | "your_password": "您的密码", 31 | "password_updated": "您的密码已经更新!", 32 | "new_password": "新密码", 33 | "login_with": "登录", 34 | "register_with": "注册" 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Requests/Permissions/CreatePermissionRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('create.permissions'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string|min:3|max:255', 28 | 'slug' => 'required|string|unique:permissions,slug', 29 | 'description' => 'nullable|string|max:255', 30 | 'model' => 'string|nullable', 31 | 'roles' => 'present|array', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Requests/Permissions/UpdatePermissionRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('update.permissions'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string|min:3|max:255', 28 | // 'slug' => 'required|string|unique:permissions,slug', 29 | 'description' => 'nullable|string|max:255', 30 | 'model' => 'string|nullable', 31 | 'roles' => 'present|array', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/js/components/common/AdminMiniCard.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 35 | -------------------------------------------------------------------------------- /config/users.php: -------------------------------------------------------------------------------- 1 | [ 6 | 'superAdmin' => [ 7 | 'enabled' => env('SEED_SUPER_ADMIN_USER_ENABLED', false), 8 | 'name' => env('SEED_SUPER_ADMIN_USER_NAME', 'Rick Sanchez'), 9 | 'email' => env('SEED_SUPER_ADMIN_USER_EMAIL', 'superadmin@superadmin.com'), 10 | 'password' => env('SEED_SUPER_ADMIN_USER_PASSWORD', 'password'), 11 | ], 12 | 'admin' => [ 13 | 'enabled' => env('SEED_ADMIN_USER_ENABLED', false), 14 | 'name' => env('SEED_ADMIN_USER_NAME', 'Mr Nimbus'), 15 | 'email' => env('SEED_ADMIN_USER_EMAIL', 'admin@admin.com'), 16 | 'password' => env('SEED_ADMIN_USER_PASSWORD', 'password'), 17 | ], 18 | 'user' => [ 19 | 'enabled' => env('SEED_USER_ENABLED', false), 20 | 'name' => env('SEED_USER_NAME', 'Scary Terr'), 21 | 'email' => env('SEED_USER_EMAIL', 'user@user.com'), 22 | 'password' => env('SEED_USER_PASSWORD', 'password'), 23 | ], 24 | ], 25 | ]; 26 | -------------------------------------------------------------------------------- /config/personal-data-export.php: -------------------------------------------------------------------------------- 1 | 'personal-data-exports', 8 | 9 | /* 10 | * If you want to keep the original directory structure for added files, 11 | */ 12 | 'keep_directory_structure' => true, 13 | 14 | /* 15 | * The amount of days the exports will be available. 16 | */ 17 | 'delete_after_days' => 5, 18 | 19 | /* 20 | * Determines whether the user should be logged in to be able 21 | * to access the export. 22 | */ 23 | 'authentication_required' => true, 24 | 25 | /* 26 | * The notification which will be sent to the user when the export 27 | * has been created. 28 | */ 29 | 'notification' => \App\Notifications\PersonalDataExportedNotification::class, 30 | 31 | /* 32 | * Configure the queue and connection used by `CreatePersonalDataExportJob` 33 | * which will create the export. 34 | */ 35 | 'job' => [ 36 | 'queue' => null, 37 | 'connection' => null, 38 | ], 39 | ]; 40 | -------------------------------------------------------------------------------- /resources/js/components/common/CircleSvg.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 44 | -------------------------------------------------------------------------------- /resources/js/components/includes/BreadcrumbOld.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 31 | 32 | 45 | -------------------------------------------------------------------------------- /database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->morphs('tokenable'); 19 | $table->string('name'); 20 | $table->string('token', 64)->unique(); 21 | $table->text('abilities')->nullable(); 22 | $table->timestamp('last_used_at')->nullable(); 23 | $table->timestamp('expires_at')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down(): void 34 | { 35 | Schema::dropIfExists('personal_access_tokens'); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Jeremy Kenedy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/CreateUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('create.users'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|min:3|max:255', 28 | 'email' => 'required|email|unique:users,email', 29 | 'password' => 'required|min:6|max:255|confirmed', 30 | 'roles' => 'present|array', 31 | 'permissions' => 'present|array', 32 | 'theme_dark' => 'nullable|boolean', 33 | 'email_verified_at' => 'nullable|boolean', 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/js/components/form/AppSettingTextInput.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 34 | -------------------------------------------------------------------------------- /app/Http/Resources/ActivityLogs/ActivityLogResource.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function toArray(Request $request): array 16 | { 17 | return [ 18 | 'id' => $this->id, 19 | 'log_name' => $this->log_name, 20 | 'description' => $this->description, 21 | 'subject_type' => $this->subject_type, 22 | 'event' => $this->event, 23 | 'causer_type' => $this->causer_type, 24 | 'causer_id' => $this->causer_id, 25 | 'properties' => $this->properties, 26 | 'batch_uuid' => $this->batch_uuid, 27 | 'created_at' => $this->created_at, 28 | 'format_created_at' => $this->created_at->diffForHumans(), 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Models/Impersonation.php: -------------------------------------------------------------------------------- 1 | 'integer', 35 | 'user_id' => 'integer', 36 | 'personal_access_token_id' => 'string', 37 | ]; 38 | 39 | public function user() 40 | { 41 | return $this->belongsTo(User::class); 42 | } 43 | 44 | public function token() 45 | { 46 | return $this->belongsTo(PersonalAccessToken::class); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /database/migrations/2022_12_06_061947_create_impersonations_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->bigInteger('personal_access_token_id')->unsigned(); 19 | $table->bigInteger('user_id')->unsigned(); 20 | $table->timestamps(); 21 | 22 | $table->foreign('personal_access_token_id')->references('id')->on('personal_access_tokens')->cascadeOnDelete(); 23 | $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down(): void 33 | { 34 | Schema::dropIfExists('impersonations'); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /database/migrations/2025_01_23_093055_create_activity_log_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('log_name')->nullable(); 19 | $table->text('description'); 20 | $table->nullableMorphs('subject', 'subject'); 21 | $table->nullableMorphs('causer', 'causer'); 22 | $table->json('properties')->nullable(); 23 | $table->timestamps(); 24 | $table->index('log_name'); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down(): void 34 | { 35 | Schema::dropIfExists(config('activitylog.table_name')); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/UpdateUserRequest.php: -------------------------------------------------------------------------------- 1 | user()->hasPermission('edit.users'); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string|min:3|max:255', 28 | // 'email' => 'required|string|email|max:255|unique:users,email,'.$user->id, 29 | 'password' => 'nullable|string|min:6|max:255|confirmed', 30 | 'roles' => 'present|array', 31 | 'permissions' => 'present|array', 32 | 'theme_dark' => 'nullable|boolean', 33 | 'email_verified_at' => 'nullable', 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/js/layouts/ErrorLayout.vue: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 28 | $schedule->command('personal-data-export:clean')->daily(); 29 | $schedule->command('generate-sitemap')->daily(); 30 | $schedule->command('model:prune')->daily(); 31 | } 32 | 33 | /** 34 | * Register the commands for the application. 35 | * 36 | * @return void 37 | */ 38 | protected function commands() 39 | { 40 | $this->load(__DIR__.'/Commands'); 41 | 42 | require base_path('routes/console.php'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/LoginController.php: -------------------------------------------------------------------------------- 1 | middleware('guest')->except('logout'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /resources/js/components/LocaleSwitcher.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /database/seeders/PermissionTableSeeder.php: -------------------------------------------------------------------------------- 1 | $permission]); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ConfirmPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /resources/js/components/includes/AdminBreadcrumb.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 41 | 42 | 47 | -------------------------------------------------------------------------------- /app/Http/Resources/Posts/PostResource.php: -------------------------------------------------------------------------------- 1 | getMedia('*')[0]->getUrl('resized-image'); 21 | } catch (Exception $e) { 22 | $resized_image = ''; 23 | } 24 | 25 | return [ 26 | 'id' => $this->id, 27 | 'title' => $this->title, 28 | 'categories' => $this->categories, 29 | 'content' => $this->content, 30 | 'original_image' => count($this->getMedia('*')) > 0 ? $this->getMedia('*')[0]->getUrl() : null, 31 | 'resized_image' => $resized_image, 32 | 'created_at' => $this->created_at, 33 | 'updated_at' => $this->updated_at, 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2022_11_28_073632_create_socialite_providers_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('user_id')->index(); 19 | $table->string('provider'); 20 | $table->string('provider_user_id')->index(); 21 | $table->longText('access_token')->nullable(); 22 | $table->longText('refresh_token')->nullable(); 23 | $table->longText('avatar')->nullable(); 24 | $table->timestamps(); 25 | 26 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down(): void 36 | { 37 | Schema::dropIfExists('socialite_providers'); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/ActivityLogController.php: -------------------------------------------------------------------------------- 1 | get('per_page', 15); // Default pagination size 15 | $search = $request->get('search'); 16 | 17 | $activity = Activity::query() 18 | ->latest() 19 | ->where('causer_id', auth()->id()) 20 | ->when($request->filled('filter'), function ($query) use ($request) { 21 | $query->where('event', $request->filter); 22 | }) 23 | ->when($search, function ($query) use ($search) { 24 | $query->where(function ($q) use ($search) { 25 | $q->where('description', 'like', '%'.$search.'%') 26 | ->orWhere('event', 'like', '%'.$search.'%'); 27 | }); 28 | }) 29 | ->paginate($perPage); 30 | 31 | return ActivityLogResource::collection($activity); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/views/auth/verify.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Verify Your Email Address') }}
9 | 10 |
11 | @if (session('resent')) 12 | 15 | @endif 16 | 17 | {{ __('Before proceeding, please check your email for a verification link.') }} 18 | {{ __('If you did not receive the email') }}, 19 |
20 | @csrf 21 | . 22 |
23 |
24 |
25 |
26 |
27 |
28 | @endsection 29 | -------------------------------------------------------------------------------- /app/Notifications/ResetPasswordNotification.php: -------------------------------------------------------------------------------- 1 | token.'?email='.$notifiable->getEmailForPasswordReset()); 19 | 20 | return (new MailMessage()) 21 | ->subject(trans('emails.password.request.subject')) 22 | ->line(trans('emails.password.request.message')) 23 | ->action(trans('emails.password.request.action'), $resetUrl) 24 | ->line(trans('emails.password.request.goodbye')); 25 | } 26 | 27 | /** 28 | * Get the array representation of the notification. 29 | * 30 | * @return array 31 | */ 32 | public function toArray(object $notifiable): array 33 | { 34 | return [ 35 | // 36 | ]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/js/components/form/AppSettingTextarea.vue: -------------------------------------------------------------------------------- 1 |