diff --git a/CHANGELOG.md b/CHANGELOG.md index 83690409..fded9e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,22 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip ### Security - Nothing +------- + +### Added +- flexbox css helper class; +- support for HTML messages inside Alert bubbles, when triggered from PHP; +- added publish lang command; +- added command to publish only the minimum amount of files needed for Backpack to work; +- ```sidebar_content.blade.php``` file, so that we can add sidebar items using a command +- ```php artisan backpack:base:add-sidebar-content``` command; +- ```php artisan backpack:base:add-custom-route``` command; +- ability for developer to use a custom auth guard; +- ability for developer to rename the ```admin``` middleware; +- ```before_styles```, ```after_styles```, ```before_scripts```, ```after_scripts``` stacks, to which developers can ```@push```; + +### Fixed +- the installation command now only publishes the minimum amount of files, by default; ## [0.8.9] - 2018-02-08 diff --git a/composer.json b/composer.json index 411e1ce4..237d84a3 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ } ], "require": { - "almasaeed2010/AdminLTE" : "2.3.*", + "almasaeed2010/AdminLTE" : "2.4.*", "laravel/framework": "5.5.*|5.6.*", "prologue/alerts": "^0.4.1", "jenssegers/date": "^3.2", diff --git a/src/BaseServiceProvider.php b/src/BaseServiceProvider.php index 5c4a5552..cfb65c56 100644 --- a/src/BaseServiceProvider.php +++ b/src/BaseServiceProvider.php @@ -10,6 +10,8 @@ class BaseServiceProvider extends ServiceProvider { protected $commands = [ \Backpack\Base\app\Console\Commands\Install::class, + \Backpack\Base\app\Console\Commands\AddSidebarContent::class, + \Backpack\Base\app\Console\Commands\AddCustomRouteContent::class, ]; /** @@ -26,6 +28,13 @@ class BaseServiceProvider extends ServiceProvider */ public $routeFilePath = '/routes/backpack/base.php'; + /** + * Where custom routes can be written, and will be registered by Backpack. + * + * @var string + */ + public $customRoutesFilePath = '/routes/backpack/custom.php'; + /** * Perform post-registration booting of services. * @@ -46,10 +55,17 @@ public function boot(\Illuminate\Routing\Router $router) __DIR__.'/config/backpack/base.php', 'backpack.base' ); - $this->registerAdminMiddleware($this->app->router); + // add the root disk to filesystem configuration + app()->config['filesystems.disks.'.config('backpack.base.root_disk_name')] = [ + 'driver' => 'local', + 'root' => base_path(), + ]; + + $this->registerMiddlewareGroup($this->app->router); + $this->loadHelpers(); $this->setupRoutes($this->app->router); + $this->setupCustomRoutes($this->app->router); $this->publishFiles(); - $this->loadHelpers(); } /** @@ -80,6 +96,21 @@ public function setupRoutes(Router $router) $this->loadRoutesFrom($routeFilePathInUse); } + /** + * Load custom routes file. + * + * @param \Illuminate\Routing\Router $router + * + * @return void + */ + public function setupCustomRoutes(Router $router) + { + // if the custom routes file is published, register its routes + if (file_exists(base_path().$this->customRoutesFilePath)) { + $this->loadRoutesFrom(base_path().$this->customRoutesFilePath); + } + } + /** * Register any package services. * @@ -111,41 +142,83 @@ public function register() if (class_exists('Backpack\Generators\GeneratorsServiceProvider')) { $this->app->register('Backpack\Generators\GeneratorsServiceProvider'); } + } else { + $this->checkLicenseCodeExists(); } // register the artisan commands $this->commands($this->commands); } - public function registerAdminMiddleware(Router $router) + public function registerMiddlewareGroup(Router $router) { - Route::aliasMiddleware('admin', \Backpack\Base\app\Http\Middleware\Admin::class); - } + $middleware_key = config('backpack.base.middleware_key'); + $middleware_class = config('backpack.base.middleware_class'); - public function publishFiles() - { - // publish config file - $this->publishes([__DIR__.'/config' => config_path()], 'config'); + if (!is_array($middleware_class)) { + $router->pushMiddlewareToGroup($middleware_key, $middleware_class); - // publish lang files - // $this->publishes([__DIR__.'/resources/lang' => resource_path('lang/vendor/backpack')], 'lang'); + return; + } - // publish views - $this->publishes([__DIR__.'/resources/views' => resource_path('views/vendor/backpack/base')], 'views'); + foreach ($middleware_class as $middleware_class) { + $router->pushMiddlewareToGroup($middleware_key, $middleware_class); + } + } - // publish error views - $this->publishes([__DIR__.'/resources/error_views' => resource_path('views/errors')], 'errors'); + public function publishFiles() + { + $error_views = [__DIR__.'/resources/error_views' => resource_path('views/errors')]; + $backpack_base_views = [__DIR__.'/resources/views' => resource_path('views/vendor/backpack/base')]; + $backpack_public_assets = [__DIR__.'/public' => public_path('vendor/backpack')]; + $backpack_lang_files = [__DIR__.'/resources/lang' => resource_path('lang/vendor/backpack')]; + $backpack_config_files = [__DIR__.'/config' => config_path()]; - // publish public Backpack assets - $this->publishes([__DIR__.'/public' => public_path('vendor/backpack')], 'public'); + // sidebar_content view, which is the only view most people need to overwrite + $backpack_sidebar_contents_view = [__DIR__.'/resources/views/inc/sidebar_content.blade.php' => resource_path('views/vendor/backpack/base/inc/sidebar_content.blade.php')]; + $backpack_custom_routes_file = [__DIR__.$this->customRoutesFilePath => base_path($this->customRoutesFilePath)]; // calculate the path from current directory to get the vendor path $vendorPath = dirname(__DIR__, 3); + $adminlte_assets = [$vendorPath.'/almasaeed2010/adminlte' => public_path('vendor/adminlte')]; + $gravatar_assets = [$vendorPath.'/creativeorange/gravatar/config' => config_path()]; + + // establish the minimum amount of files that need to be published, for Backpack to work; there are the files that will be published by the install command + $minimum = array_merge( + $error_views, + // $backpack_base_views, + $backpack_public_assets, + // $backpack_lang_files, + $backpack_config_files, + $backpack_sidebar_contents_view, + $backpack_custom_routes_file, + $adminlte_assets, + $gravatar_assets + ); - // publish public AdminLTE assets - $this->publishes([$vendorPath.'/almasaeed2010/adminlte' => public_path('vendor/adminlte')], 'adminlte'); + // register all possible publish commands and assign tags to each + $this->publishes($backpack_config_files, 'config'); + $this->publishes($backpack_lang_files, 'lang'); + $this->publishes($backpack_base_views, 'views'); + $this->publishes($backpack_sidebar_contents_view, 'sidebar_content'); + $this->publishes($error_views, 'errors'); + $this->publishes($backpack_public_assets, 'public'); + $this->publishes($backpack_custom_routes_file, 'custom_routes'); + $this->publishes($adminlte_assets, 'adminlte'); + $this->publishes($gravatar_assets, 'gravatar'); + $this->publishes($minimum, 'minimum'); + } - // publish public Gravatar assets - $this->publishes([$vendorPath.'/creativeorange/gravatar/config' => config_path()], 'gravatar'); + /** + * Check to to see if a license code exists. + * If it does not, throw a notification bubble. + * + * @return void + */ + private function checkLicenseCodeExists() + { + if (!config('backpack.base.license_code')) { + \Alert::add('warning', "You're using unlicensed software. Please ask your web developer to purchase a license code to hide this message."); + } } } diff --git a/src/app/Console/Commands/AddCustomRouteContent.php b/src/app/Console/Commands/AddCustomRouteContent.php new file mode 100644 index 00000000..ebc6e85a --- /dev/null +++ b/src/app/Console/Commands/AddCustomRouteContent.php @@ -0,0 +1,85 @@ +argument('code'); + + if ($disk->exists($path)) { + $old_file_content = Storage::disk($disk_name)->get($path); + + // insert the given code before the file's last line + $file_lines = explode(PHP_EOL, $old_file_content); + $number_of_lines = count($file_lines); + $file_lines[$number_of_lines] = $file_lines[$number_of_lines - 1]; + $file_lines[$number_of_lines - 1] = ' '.$code; + $new_file_content = implode(PHP_EOL, $file_lines); + + if ($disk->put($path, $new_file_content)) { + $this->info('Successfully added code to '.$path); + } else { + $this->error('Could not write to file: '.$path); + } + } else { + $command = 'php artisan vendor:publish --provider="Backpack\Base\BaseServiceProvider" --tag=custom_routes'; + + $process = new Process($command, null, null, null, 300, null); + + $process->run(function ($type, $buffer) { + if (Process::ERR === $type) { + $this->line($buffer); + } else { + $this->line($buffer); + } + }); + + // executes after the command finishes + if (!$process->isSuccessful()) { + throw new ProcessFailedException($process); + } + + $this->handle(); + } + } +} diff --git a/src/app/Console/Commands/AddSidebarContent.php b/src/app/Console/Commands/AddSidebarContent.php new file mode 100644 index 00000000..943df445 --- /dev/null +++ b/src/app/Console/Commands/AddSidebarContent.php @@ -0,0 +1,59 @@ +argument('code'); + + if ($disk->exists($path)) { + $contents = Storage::disk($disk_name)->get($path); + + if ($disk->put($path, $contents.PHP_EOL.$code)) { + $this->info('Successfully added code to sidebar_content file.'); + } else { + $this->error('Could not write to sidebar_content file.'); + } + } else { + $this->error("The sidebar_content file does not exist. Make sure Backpack\Base is properly installed."); + } + } +} diff --git a/src/app/Console/Commands/Install.php b/src/app/Console/Commands/Install.php index e32abad0..7ceea21a 100644 --- a/src/app/Console/Commands/Install.php +++ b/src/app/Console/Commands/Install.php @@ -55,7 +55,7 @@ public function handle() $this->executeProcess('composer require laracasts/generators:dev-master --dev'); $this->line(' Publishing configs, langs, views and AdminLTE files'); - $this->executeProcess('php artisan vendor:publish --provider="Backpack\Base\BaseServiceProvider"'); + $this->executeProcess('php artisan vendor:publish --provider="Backpack\Base\BaseServiceProvider" --tag=minimum'); $this->line(' Publishing config for notifications - prologue/alerts'); $this->executeProcess('php artisan vendor:publish --provider="Prologue\Alerts\AlertsServiceProvider"'); diff --git a/src/app/Http/Controllers/AdminController.php b/src/app/Http/Controllers/AdminController.php index 7ee790bd..d818bef5 100644 --- a/src/app/Http/Controllers/AdminController.php +++ b/src/app/Http/Controllers/AdminController.php @@ -11,7 +11,7 @@ class AdminController extends Controller */ public function __construct() { - $this->middleware('admin'); + $this->middleware(backpack_middleware()); } /** @@ -34,6 +34,6 @@ public function dashboard() public function redirect() { // The '/admin' route is not to be used as a page, because it breaks the menu's active state. - return redirect(config('backpack.base.route_prefix').'/dashboard'); + return redirect(backpack_url('dashboard')); } } diff --git a/src/app/Http/Controllers/Auth/ForgotPasswordController.php b/src/app/Http/Controllers/Auth/ForgotPasswordController.php index 65060e77..6a0245e1 100644 --- a/src/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/src/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -4,6 +4,7 @@ use Backpack\Base\app\Http\Controllers\Controller; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; +use Illuminate\Support\Facades\Password; class ForgotPasswordController extends Controller { @@ -29,7 +30,9 @@ class ForgotPasswordController extends Controller */ public function __construct() { - $this->middleware('guest'); + $guard = backpack_guard_name(); + + $this->middleware("guest:$guard"); } // ------------------------------------------------------- @@ -47,4 +50,16 @@ public function showLinkRequestForm() return view('backpack::auth.passwords.email', $this->data); } + + /** + * Get the broker to be used during password reset. + * + * @return \Illuminate\Contracts\Auth\PasswordBroker + */ + public function broker() + { + $passwords = config('backpack.base.passwords', config('auth.defaults.passwords')); + + return Password::broker($passwords); + } } diff --git a/src/app/Http/Controllers/Auth/LoginController.php b/src/app/Http/Controllers/Auth/LoginController.php index 9cde6abf..9926d9d2 100644 --- a/src/app/Http/Controllers/Auth/LoginController.php +++ b/src/app/Http/Controllers/Auth/LoginController.php @@ -31,23 +31,35 @@ class LoginController extends Controller */ public function __construct() { - $this->middleware('guest', ['except' => 'logout']); + $guard = backpack_guard_name(); + + $this->middleware("guest:$guard", ['except' => 'logout']); // ---------------------------------- // Use the admin prefix in all routes + // ---------------------------------- // If not logged in redirect here. $this->loginPath = property_exists($this, 'loginPath') ? $this->loginPath - : config('backpack.base.route_prefix', 'admin').'/login'; + : backpack_url('login'); // Redirect here after successful login. $this->redirectTo = property_exists($this, 'redirectTo') ? $this->redirectTo - : config('backpack.base.route_prefix', 'admin').'/dashboard'; + : backpack_url('dashboard'); // Redirect here after logout. $this->redirectAfterLogout = property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout - : config('backpack.base.route_prefix', 'admin'); - // ---------------------------------- + : backpack_url(); + } + + /** + * Return custom username for authentication. + * + * @return string + */ + public function username() + { + return backpack_authentication_column(); } // ------------------------------------------------------- @@ -76,9 +88,19 @@ public function showLoginForm() public function logout(Request $request) { // Do the default logout procedure - $this->defaultLogout($request); + $this->guard()->logout(); // And redirect to custom location return redirect($this->redirectAfterLogout); } + + /** + * Get the guard to be used during logout. + * + * @return \Illuminate\Contracts\Auth\StatefulGuard + */ + protected function guard() + { + return backpack_auth(); + } } diff --git a/src/app/Http/Controllers/Auth/MyAccountController.php b/src/app/Http/Controllers/Auth/MyAccountController.php index af08292d..f27aff09 100644 --- a/src/app/Http/Controllers/Auth/MyAccountController.php +++ b/src/app/Http/Controllers/Auth/MyAccountController.php @@ -15,7 +15,7 @@ class MyAccountController extends Controller public function __construct() { - $this->middleware('admin'); + $this->middleware(backpack_middleware()); } /** @@ -80,6 +80,6 @@ public function postChangePasswordForm(ChangePasswordRequest $request) */ protected function guard() { - return Auth::guard(); + return backpack_auth(); } } diff --git a/src/app/Http/Controllers/Auth/RegisterController.php b/src/app/Http/Controllers/Auth/RegisterController.php index 9836bca4..fa99e141 100644 --- a/src/app/Http/Controllers/Auth/RegisterController.php +++ b/src/app/Http/Controllers/Auth/RegisterController.php @@ -30,7 +30,9 @@ class RegisterController extends Controller */ public function __construct() { - $this->middleware('guest'); + $guard = backpack_guard_name(); + + $this->middleware("guest:$guard"); // Where to redirect users after login / registration. $this->redirectTo = property_exists($this, 'redirectTo') ? $this->redirectTo @@ -49,11 +51,12 @@ protected function validator(array $data) $user_model_fqn = config('backpack.base.user_model_fqn'); $user = new $user_model_fqn(); $users_table = $user->getTable(); + $email_validation = backpack_authentication_column() == 'email' ? 'email|' : ''; return Validator::make($data, [ - 'name' => 'required|max:255', - 'email' => 'required|email|max:255|unique:'.$users_table, - 'password' => 'required|min:6|confirmed', + 'name' => 'required|max:255', + backpack_authentication_column() => 'required|'.$email_validation.'max:255|unique:'.$users_table, + 'password' => 'required|min:6|confirmed', ]); } @@ -70,9 +73,9 @@ protected function create(array $data) $user = new $user_model_fqn(); return $user->create([ - 'name' => $data['name'], - 'email' => $data['email'], - 'password' => bcrypt($data['password']), + 'name' => $data['name'], + backpack_authentication_column() => $data[backpack_authentication_column()], + 'password' => bcrypt($data['password']), ]); } @@ -113,4 +116,14 @@ public function register(Request $request) return redirect($this->redirectPath()); } + + /** + * Get the guard to be used during registration. + * + * @return \Illuminate\Contracts\Auth\StatefulGuard + */ + protected function guard() + { + return backpack_auth(); + } } diff --git a/src/app/Http/Controllers/Auth/ResetPasswordController.php b/src/app/Http/Controllers/Auth/ResetPasswordController.php index efeb8ee0..f371ee05 100644 --- a/src/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/src/app/Http/Controllers/Auth/ResetPasswordController.php @@ -5,6 +5,7 @@ use Backpack\Base\app\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Password; class ResetPasswordController extends Controller { @@ -30,7 +31,13 @@ class ResetPasswordController extends Controller */ public function __construct() { - $this->middleware('guest'); + $guard = backpack_guard_name(); + + $this->middleware("guest:$guard"); + + if (!backpack_users_have_email()) { + abort(501, trans('backpack::base.no_email_column')); + } // where to redirect after password was reset $this->redirectTo = property_exists($this, 'redirectTo') ? $this->redirectTo : config('backpack.base.route_prefix', 'admin').'/dashboard'; @@ -58,4 +65,26 @@ public function showResetForm(Request $request, $token = null) ['token' => $token, 'email' => $request->email] ); } + + /** + * Get the broker to be used during password reset. + * + * @return \Illuminate\Contracts\Auth\PasswordBroker + */ + public function broker() + { + $passwords = config('backpack.base.passwords', config('auth.defaults.passwords')); + + return Password::broker($passwords); + } + + /** + * Get the guard to be used during password reset. + * + * @return \Illuminate\Contracts\Auth\StatefulGuard + */ + protected function guard() + { + return backpack_auth(); + } } diff --git a/src/app/Http/Middleware/Admin.php b/src/app/Http/Middleware/CheckIfAdmin.php similarity index 61% rename from src/app/Http/Middleware/Admin.php rename to src/app/Http/Middleware/CheckIfAdmin.php index 8a622c15..aaf0d0f7 100644 --- a/src/app/Http/Middleware/Admin.php +++ b/src/app/Http/Middleware/CheckIfAdmin.php @@ -3,26 +3,24 @@ namespace Backpack\Base\app\Http\Middleware; use Closure; -use Illuminate\Support\Facades\Auth; -class Admin +class CheckIfAdmin { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next - * @param string|null $guard * * @return mixed */ - public function handle($request, Closure $next, $guard = null) + public function handle($request, Closure $next) { - if (Auth::guard($guard)->guest()) { + if (backpack_auth()->guest()) { if ($request->ajax() || $request->wantsJson()) { return response(trans('backpack::base.unauthorized'), 401); } else { - return redirect()->guest(config('backpack.base.route_prefix', 'admin').'/login'); + return redirect()->guest(backpack_url('login')); } } diff --git a/src/app/Http/Requests/AccountInfoRequest.php b/src/app/Http/Requests/AccountInfoRequest.php index 99b32ce5..0fd972fe 100644 --- a/src/app/Http/Requests/AccountInfoRequest.php +++ b/src/app/Http/Requests/AccountInfoRequest.php @@ -3,7 +3,6 @@ namespace Backpack\Base\app\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Auth; use Illuminate\Validation\Rule; class AccountInfoRequest extends FormRequest @@ -16,7 +15,7 @@ class AccountInfoRequest extends FormRequest public function authorize() { // only allow updates if the user is logged in - return Auth::check(); + return backpack_auth()->check(); } /** @@ -26,7 +25,7 @@ public function authorize() */ protected function validationData() { - return $this->only('email', 'name'); + return $this->only(backpack_authentication_column(), 'name'); } /** @@ -36,12 +35,12 @@ protected function validationData() */ public function rules() { - $user = Auth::user(); + $user = backpack_auth()->user(); return [ - 'email' => [ + backpack_authentication_column() => [ 'required', - 'email', + backpack_authentication_column() == 'email' ? 'email' : '', Rule::unique($user->getTable())->ignore($user->getKey()), ], 'name' => 'required', diff --git a/src/app/Http/Requests/ChangePasswordRequest.php b/src/app/Http/Requests/ChangePasswordRequest.php index d0fa182b..518c339f 100644 --- a/src/app/Http/Requests/ChangePasswordRequest.php +++ b/src/app/Http/Requests/ChangePasswordRequest.php @@ -3,7 +3,6 @@ namespace Backpack\Base\app\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; class ChangePasswordRequest extends FormRequest @@ -16,7 +15,7 @@ class ChangePasswordRequest extends FormRequest public function authorize() { // only allow updates if the user is logged in - return Auth::check(); + return backpack_auth()->check(); } /** @@ -44,7 +43,7 @@ public function withValidator($validator) { $validator->after(function ($validator) { // check old password matches - if (!Hash::check($this->input('old_password'), Auth::user()->password)) { + if (!Hash::check($this->input('old_password'), backpack_auth()->user()->password)) { $validator->errors()->add('old_password', trans('backpack::base.old_password_incorrect')); } }); diff --git a/src/app/Models/BackpackUser.php b/src/app/Models/BackpackUser.php new file mode 100644 index 00000000..abc99def --- /dev/null +++ b/src/app/Models/BackpackUser.php @@ -0,0 +1,39 @@ +notify(new ResetPasswordNotification($token)); + } + + /** + * Build the mail representation of the notification. + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->line([ + trans('backpack.base.password_reset.line_1'), + trans('backpack.base.password_reset.line_2'), + ]) + ->action(trans('backpack.base.password_reset.button'), url(config('backpack.base.route_prefix').'/password/reset', $this->token)) + ->line(trans('backpack.base.password_reset.notice')); + } +} diff --git a/src/config/backpack/base.php b/src/config/backpack/base.php index bff9fee8..86007fae 100644 --- a/src/config/backpack/base.php +++ b/src/config/backpack/base.php @@ -74,12 +74,36 @@ /* |-------------------------------------------------------------------------- - | User Model + | Authentication |-------------------------------------------------------------------------- */ // Fully qualified namespace of the User model - 'user_model_fqn' => '\App\User', + 'user_model_fqn' => \Backpack\Base\app\Models\BackpackUser::class, + + // The classes for the middleware to check if the visitor is an admin + // Can be a single class or an array of clases + 'middleware_class' => [ + \Backpack\Base\app\Http\Middleware\CheckIfAdmin::class, + ], + + // Alias for that middleware + 'middleware_key' => 'admin', + // Note: It's recommended to use the backpack_middleware() helper everywhere, which pulls this key for you. + + // Username column for authentication + // The Backpack default is the same as the Laravel default (email) + // If you need to switch to username, you also need to create that column in your db + 'authentication_column' => 'email', + 'authentication_column_name' => trans('backpack::base.email_address'), + + // The guard that protects the Backpack admin panel. + // If null, the config.auth.defaults.guard value will be used. + 'guard' => null, + + // The password reset configuration for Backpack. + // If null, the config.auth.defaults.passwords value will be used. + 'passwords' => null, // What kind of avatar will you like to show to the user? // Default: gravatar (automatically use the gravatar for his email) @@ -88,14 +112,27 @@ // - example_method_name (specify the method on the User model that returns the URL) 'avatar_type' => 'gravatar', + /* + |-------------------------------------------------------------------------- + | File System + |-------------------------------------------------------------------------- + */ + + // Backpack\Base sets up its own filesystem disk, just like you would by + // adding an entry to your config/filesystems.php. It points to the root + // of your project and it's used throughout all Backpack packages. + // + // You can rename this disk here. Default: root + 'root_disk_name' => 'root', + /* |-------------------------------------------------------------------------- | License Code |-------------------------------------------------------------------------- | | If you, your employer or your client make money by using Backpack, you need - | to purchase a license code. A license code will be provided after purchase, - | which you can put here or in your ENV file. + | to purchase a license. A license code will be provided after purchase, + | which you can put here or in your ENV file in staging & production. | | More info and payment form on: | https://www.backpackforlaravel.com diff --git a/src/helpers.php b/src/helpers.php index 0444e472..3cc9421b 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -17,6 +17,34 @@ function backpack_url($path = null) } } +if (!function_exists('backpack_authentication_column')) { + /** + * Return the username column name. + * The Laravel default (and Backpack default) is 'email'. + * + * @return string + */ + function backpack_authentication_column() + { + return config('backpack.base.authentication_column', 'email'); + } +} + +if (!function_exists('backpack_users_have_email')) { + /** + * Check if the email column is present on the user table. + * + * @return string + */ + function backpack_users_have_email() + { + $user_model_fqn = config('backpack.base.user_model_fqn'); + $user = new $user_model_fqn(); + + return \Schema::hasColumn($user->getTable(), 'email'); + } +} + if (!function_exists('backpack_avatar')) { /** * Returns the avatar URL of a user. @@ -27,13 +55,19 @@ function backpack_url($path = null) */ function backpack_avatar_url($user) { + $placeholder = 'https://placehold.it/160x160/00a65a/ffffff/&text='.$user->name[0]; + switch (config('backpack.base.avatar_type')) { case 'gravatar': - return Gravatar::fallback('https://placehold.it/160x160/00a65a/ffffff/&text='.$user->name[0])->get($user->email); + if (backpack_users_have_email()) { + return Gravatar::fallback('https://placehold.it/160x160/00a65a/ffffff/&text='.$user->name[0])->get($user->email); + } else { + return $placeholder; + } break; case 'placehold': - return 'https://placehold.it/160x160/00a65a/ffffff/&text='.$user->name[0]; + return $placeholder; break; default: @@ -42,3 +76,53 @@ function backpack_avatar_url($user) } } } + +if (!function_exists('backpack_middleware')) { + /** + * Return the key of the middleware used across Backpack. + * That middleware checks if the visitor is an admin. + * + * @param $path + * + * @return string + */ + function backpack_middleware() + { + return config('backpack.base.middleware_key', 'admin'); + } +} + +if (!function_exists('backpack_guard_name')) { + /* + * Returns the name of the guard defined + * by the application config + */ + function backpack_guard_name() + { + return config('backpack.base.guard', config('auth.defaults.guard')); + } +} + +if (!function_exists('backpack_auth')) { + /* + * Returns the user instance if it exists + * of the currently authenticated admin + * based off the defined guard. + */ + function backpack_auth() + { + return \Auth::guard(backpack_guard_name()); + } +} + +if (!function_exists('backpack_user')) { + /* + * Returns back a user instance without + * the admin guard, however allows you + * to pass in a custom guard if you like. + */ + function backpack_user() + { + return backpack_auth()->user(); + } +} diff --git a/src/public/backpack.base.css b/src/public/backpack.base.css index 63b3672f..998de222 100644 --- a/src/public/backpack.base.css +++ b/src/public/backpack.base.css @@ -841,6 +841,13 @@ body[class^='skin-purple'] .pagination>.active>span:hover { border-color: #f8d053; } + /* FLEXBOX HELPERS */ + + .display-flex-wrap { + display: flex; + flex-wrap: wrap; + } + /* BORDER RADIUS HELPERS */ .b-rad-sm { diff --git a/src/resources/lang/en/base.php b/src/resources/lang/en/base.php index 8597403a..07ffb736 100644 --- a/src/resources/lang/en/base.php +++ b/src/resources/lang/en/base.php @@ -9,6 +9,7 @@ */ 'registration_closed' => 'Registration is closed.', + 'no_email_column' => 'Users do not have an associated email address.', 'first_page_you_see' => 'The first page you see after login', 'login_status' => 'Login status', 'logged_in' => 'You are logged in!', @@ -47,4 +48,11 @@ 'account_updated' => 'Account updated successfully.', 'unknown_error' => 'An unknown error has occured. Please try again.', 'error_saving' => 'Error while saving. Please try again.', + + 'password_reset' => [ + 'line_1' => 'You are receiving this email because we received a password reset request for your account.', + 'line_2' => 'Click the button below to reset your password:', + 'button' => 'Reset Password', + 'notice' => 'If you did not request a password reset, no further action is required.', + ], ]; diff --git a/src/resources/views/auth/account/sidemenu.blade.php b/src/resources/views/auth/account/sidemenu.blade.php index 75b19f62..ac768cd0 100644 --- a/src/resources/views/auth/account/sidemenu.blade.php +++ b/src/resources/views/auth/account/sidemenu.blade.php @@ -1,7 +1,7 @@
- -

{{ Auth::user()->name }}

+ +

{{ backpack_auth()->user()->name }}


diff --git a/src/resources/views/auth/account/update_info.blade.php b/src/resources/views/auth/account/update_info.blade.php index ea38c3ef..e95c71bf 100644 --- a/src/resources/views/auth/account/update_info.blade.php +++ b/src/resources/views/auth/account/update_info.blade.php @@ -72,16 +72,16 @@ $field = 'name'; @endphp - +
@php - $label = trans('backpack::base.email_address'); - $field = 'email'; + $label = config('backpack.base.authentication_column_name'); + $field = backpack_authentication_column(); @endphp - +
diff --git a/src/resources/views/auth/login.blade.php b/src/resources/views/auth/login.blade.php index e7e1b267..a026800e 100644 --- a/src/resources/views/auth/login.blade.php +++ b/src/resources/views/auth/login.blade.php @@ -11,15 +11,15 @@
{!! csrf_field() !!} -
- +
+
- + - @if ($errors->has('email')) + @if ($errors->has(backpack_authentication_column())) - {{ $errors->first('email') }} + {{ $errors->first(backpack_authentication_column()) }} @endif
@@ -55,7 +55,9 @@ {{ trans('backpack::base.login') }} + @if (backpack_users_have_email()) {{ trans('backpack::base.forgot_your_password') }} + @endif
diff --git a/src/resources/views/auth/register.blade.php b/src/resources/views/auth/register.blade.php index 273f2c7e..3221a157 100644 --- a/src/resources/views/auth/register.blade.php +++ b/src/resources/views/auth/register.blade.php @@ -25,15 +25,15 @@ -
- +
+
- + - @if ($errors->has('email')) + @if ($errors->has(backpack_authentication_column())) - {{ $errors->first('email') }} + {{ $errors->first(backpack_authentication_column()) }} @endif
diff --git a/src/resources/views/inc/alerts.blade.php b/src/resources/views/inc/alerts.blade.php index 381d7436..023e791e 100644 --- a/src/resources/views/inc/alerts.blade.php +++ b/src/resources/views/inc/alerts.blade.php @@ -13,7 +13,7 @@ $(function(){ new PNotify({ // title: 'Regular Notice', - text: "{{ $message }}", + text: "{!! str_replace('"', "'", $message) !!}", type: "{{ $type }}", icon: false }); diff --git a/src/resources/views/inc/menu.blade.php b/src/resources/views/inc/menu.blade.php index 1639c6a7..627b375e 100644 --- a/src/resources/views/inc/menu.blade.php +++ b/src/resources/views/inc/menu.blade.php @@ -19,8 +19,8 @@ @if (config('backpack.base.setup_auth_routes')) - @if (Auth::guest()) -
  • {{ trans('backpack::base.login') }}
  • + @if (backpack_auth()->guest()) +
  • {{ trans('backpack::base.login') }}
  • @if (config('backpack.base.registration_open'))
  • {{ trans('backpack::base.register') }}
  • @endif diff --git a/src/resources/views/inc/sidebar.blade.php b/src/resources/views/inc/sidebar.blade.php index 0b4127f5..3f68429b 100644 --- a/src/resources/views/inc/sidebar.blade.php +++ b/src/resources/views/inc/sidebar.blade.php @@ -1,4 +1,4 @@ -@if (Auth::check()) +@if (backpack_auth()->check())