first upload all files

This commit is contained in:
NW
2023-06-11 13:14:03 +01:00
parent f14dbc52b5
commit c08b36d1b6
1705 changed files with 106852 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
<?php
namespace Modules\User\Admin;
use Modules\Admin\Ui\Tab;
use Modules\Admin\Ui\Tabs;
class ProfileTabs extends Tabs
{
/**
* Make new tabs with groups.
*
* @return void
*/
public function make()
{
$this->group('profile_information', trans('user::users.tabs.group.profile_information'))
->active()
->add($this->account())
->add($this->newPassword());
}
private function account()
{
return tap(new Tab('account', trans('user::users.tabs.account')), function (Tab $tab) {
$tab->active();
$tab->weight(5);
$tab->fields(['first_name', 'last_name', 'email']);
$tab->view('user::admin.profile.tabs.account');
});
}
private function newPassword()
{
return tap(new Tab('newPassword', trans('user::users.tabs.new_password')), function (Tab $tab) {
$tab->weight(10);
$tab->fields(['password', 'password_confirmation']);
$tab->view('user::admin.profile.tabs.new_password');
});
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\User\Admin;
use Modules\Admin\Ui\Tab;
use Modules\Admin\Ui\Tabs;
use Modules\User\Repositories\Permission;
class RoleTabs extends Tabs
{
public function make()
{
$this->group('role_information', trans('user::roles.tabs.role_information'))
->active()
->add($this->general())
->add($this->permissions());
}
private function general()
{
return tap(new Tab('general', trans('user::roles.tabs.general')), function (Tab $tab) {
$tab->active();
$tab->weight(10);
$tab->fields('name');
$tab->view('user::admin.roles.tabs.general');
});
}
private function permissions()
{
return tap(new Tab('permissions', trans('user::roles.tabs.permissions')), function (Tab $tab) {
$tab->weight(20);
$tab->view(function ($data) {
return view('user::admin.partials.permissions.index', [
'entity' => $data['role'],
'permissions' => Permission::all(),
]);
});
});
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Admin;
use Modules\Admin\Ui\AdminTable;
class UserTable extends AdminTable
{
/**
* Raw columns that will not be escaped.
*
* @var array
*/
protected $rawColumns = ['last_login'];
/**
* Make table response for the resource.
*
* @return \Illuminate\Http\JsonResponse
*/
public function make()
{
return $this->newTable()
->editColumn('last_login', function ($user) {
return view('admin::partials.table.date')->with('date', $user->last_login);
});
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Modules\User\Admin;
use Modules\Admin\Ui\Tab;
use Modules\Admin\Ui\Tabs;
use Modules\User\Entities\Role;
use Modules\User\Repositories\Permission;
class UserTabs extends Tabs
{
public function make()
{
$this->group('user_information', trans('user::users.tabs.group.user_information'))
->active()
->add($this->account())
->add($this->permissions())
->add($this->newPassword());
}
private function account()
{
return tap(new Tab('account', trans('user::users.tabs.account')), function (Tab $tab) {
$tab->active();
$tab->weight(10);
$tab->fields([
'first_name',
'last_name',
'email',
'phone',
'activated',
'roles',
]);
$tab->view('user::admin.users.tabs.account', [
'roles' => Role::list(),
]);
});
}
private function permissions()
{
return tap(new Tab('permissions', trans('user::users.tabs.permissions')), function (Tab $tab) {
$tab->weight(20);
$tab->view(function ($data) {
return view('user::admin.partials.permissions.index', [
'entity' => $data['user'],
'permissions' => Permission::all(),
]);
});
});
}
private function newPassword()
{
if (! request()->routeIs('admin.users.edit')) {
return;
}
return tap(new Tab('new_password', trans('user::users.tabs.new_password')), function (Tab $tab) {
$tab->weight(30);
$tab->fields(['password', 'password_confirmation']);
$tab->view('user::admin.users.tabs.new_password');
});
}
}

View File

@@ -0,0 +1,24 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Define which assets will be available through the asset manager
|--------------------------------------------------------------------------
| These assets are registered on the asset manager
*/
'all_assets' => [
'admin.user.css' => ['module' => 'user:admin/css/user.css'],
'admin.user.js' => ['module' => 'user:admin/js/user.js'],
'admin.login.css' => ['module' => 'user:admin/css/login.css'],
'admin.login.js' => ['module' => 'user:admin/js/login.js'],
],
/*
|--------------------------------------------------------------------------
| Define which default assets will always be included in your pages
| through the asset pipeline
|--------------------------------------------------------------------------
*/
'required_assets' => [],
];

View File

@@ -0,0 +1,16 @@
<?php
return [
'admin.users' => [
'index' => 'user::permissions.users.index',
'create' => 'user::permissions.users.create',
'edit' => 'user::permissions.users.edit',
'destroy' => 'user::permissions.users.destroy',
],
'admin.roles' => [
'index' => 'user::permissions.roles.index',
'create' => 'user::permissions.roles.create',
'edit' => 'user::permissions.roles.edit',
'destroy' => 'user::permissions.roles.destroy',
],
];

View File

@@ -0,0 +1,122 @@
<?php
namespace Modules\User\Contracts;
use Modules\User\Entities\Role;
use Modules\User\Entities\User;
interface Authentication
{
/**
* Authenticate a user.
*
* @param array $credentials
* @param bool $remember
* @return mixed
*/
public function login($credentials, $remember = false);
/**
* Register a new user.
*
* @param array $data
* @return bool
*/
public function register($data);
/**
* Register and activate a new user.
*
* @param array $data
* @return \Modules\User\Entities\User
*/
public function registerAndActivate($data);
/**
* Activate the given used id.
*
* @param int $userId
* @param string $code
* @return mixed
*/
public function activate($userId, $code);
/**
* Assign a role to the given user.
*
* @param \Modules\User\Entities\User $user
* @param \Modules\User\Entities\Role $role
* @return void
*/
public function assignRole(User $user, Role $role);
/**
* Log the user out of the application.
*
* @return bool
*/
public function logout();
/**
* Create an activation code for the given user.
*
* @param \Modules\User\Entities\User $user
* @return \Cartalyst\Sentinel\Activations\ActivationInterface
*/
public function createActivation(User $user);
/**
* Create a reminders code for the given user.
*
* @param \Modules\User\Entities\User $user
* @return string
*/
public function createReminderCode(User $user);
/**
* Completes the reset password process.
*
* @param \Modules\User\Entities\User $user
* @param string $code
* @param string $password
* @return bool
*/
public function completeResetPassword(User $user, $code, $password);
/**
* Determines if the current user has access to the given permissions.
*
* @param array|string $permissions
* @return bool
*/
public function hasAccess($permissions);
/**
* Determine if the user has access to the any given permissions
*
* @param array|string $permissions
* @return bool
*/
public function hasAnyAccess($permissions);
/**
* Check if the user is logged in.
*
* @return bool
*/
public function check();
/**
* Get the currently logged in user.
*
* @return \Modules\User\Entities\User
*/
public function user();
/**
* Get the ID for the currently authenticated user.
*
* @return int|null
*/
public function id();
}

View File

@@ -0,0 +1,13 @@
<?php
use Faker\Generator;
use Modules\User\Entities\User;
$factory->define(User::class, function (Generator $faker) {
return [
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'email' => $faker->safeEmail,
'password' => bcrypt(123456),
];
});

View File

@@ -0,0 +1,128 @@
<?php
/**
* Part of the Sentinel package.
*
* NOTICE OF LICENSE
*
* Licensed under the 3-clause BSD License.
*
* This source file is subject to the 3-clause BSD License that is
* bundled with this package in the LICENSE file.
*
* @package Sentinel
* @version 2.0.12
* @author Cartalyst LLC
* @license BSD License (3-clause)
* @copyright (c) 2011-2015, Cartalyst LLC
* @link http://cartalyst.com
*/
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MigrationCartalystSentinel extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
$table->string('password');
$table->text('permissions')->nullable();
$table->datetime('last_login')->nullable();
$table->timestamps();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->text('permissions')->nullable();
$table->timestamps();
});
Schema::create('role_translations', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->unsigned();
$table->string('locale');
$table->string('name');
$table->unique(['role_id', 'locale']);
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
});
Schema::create('user_roles', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->timestamps();
$table->primary(['user_id', 'role_id']);
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
});
Schema::create('activations', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->index();
$table->string('code');
$table->boolean('completed')->default(false);
$table->datetime('completed_at')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Schema::create('persistences', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('code')->unique();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Schema::create('reminders', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('code');
$table->boolean('completed')->default(false);
$table->datetime('completed_at')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Schema::create('throttle', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->string('type');
$table->string('ip')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('throttle');
Schema::dropIfExists('reminders');
Schema::dropIfExists('persistences');
Schema::dropIfExists('activations');
Schema::dropIfExists('user_roles');
Schema::dropIfExists('role_translations');
Schema::dropIfExists('roles');
Schema::dropIfExists('users');
}
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddPhoneColumnToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->after('email');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('phone');
});
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace Modules\User\Database\Seeders;
use Illuminate\Database\Seeder;
use Modules\User\Entities\Role;
class RolesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Role::create(['name' => 'Admin', 'permissions' => $this->getAdminRolePermissions()]);
Role::create(['name' => 'Customer']);
}
/**
* Get admin role permissions.
*
* @return array
*/
private function getAdminRolePermissions()
{
return [
// users
'admin.users.index' => true,
'admin.users.create' => true,
'admin.users.edit' => true,
'admin.users.destroy' => true,
// roles
'admin.roles.index' => true,
'admin.roles.create' => true,
'admin.roles.edit' => true,
'admin.roles.destroy' => true,
// products
'admin.products.index' => true,
'admin.products.create' => true,
'admin.products.edit' => true,
'admin.products.destroy' => true,
// brands
'admin.brands.index' => true,
'admin.brands.create' => true,
'admin.brands.edit' => true,
'admin.brands.destroy' => true,
// attributes
'admin.attributes.index' => true,
'admin.attributes.create' => true,
'admin.attributes.edit' => true,
'admin.attributes.destroy' => true,
// attribute sets
'admin.attribute_sets.index' => true,
'admin.attribute_sets.create' => true,
'admin.attribute_sets.edit' => true,
'admin.attribute_sets.destroy' => true,
// options
'admin.options.index' => true,
'admin.options.create' => true,
'admin.options.edit' => true,
'admin.options.destroy' => true,
// filters
'admin.filters.index' => true,
'admin.filters.create' => true,
'admin.filters.edit' => true,
'admin.filters.destroy' => true,
// reviews
'admin.reviews.index' => true,
'admin.reviews.create' => true,
'admin.reviews.edit' => true,
'admin.reviews.destroy' => true,
// categories
'admin.categories.index' => true,
'admin.categories.create' => true,
'admin.categories.edit' => true,
'admin.categories.destroy' => true,
// tags
'admin.tags.index' => true,
'admin.tags.create' => true,
'admin.tags.edit' => true,
'admin.tags.destroy' => true,
// orders
'admin.orders.index' => true,
'admin.orders.show' => true,
'admin.orders.edit' => true,
// flash sales
'admin.flash_sales.index' => true,
'admin.flash_sales.create' => true,
'admin.flash_sales.edit' => true,
'admin.flash_sales.destroy' => true,
// transactions
'admin.transactions.index' => true,
// coupons
'admin.coupons.index' => true,
'admin.coupons.create' => true,
'admin.coupons.edit' => true,
'admin.coupons.destroy' => true,
// menus
'admin.menus.index' => true,
'admin.menus.create' => true,
'admin.menus.edit' => true,
'admin.menus.destroy' => true,
'admin.menu_items.index' => true,
'admin.menu_items.create' => true,
'admin.menu_items.edit' => true,
'admin.menu_items.destroy' => true,
// Media
'admin.media.index' => true,
'admin.media.create' => true,
'admin.media.destroy' => true,
// pages
'admin.pages.index' => true,
'admin.pages.create' => true,
'admin.pages.edit' => true,
'admin.pages.destroy' => true,
// currency rates
'admin.currency_rates.index' => true,
'admin.currency_rates.edit' => true,
// tax
'admin.taxes.index' => true,
'admin.taxes.create' => true,
'admin.taxes.edit' => true,
'admin.taxes.destroy' => true,
// translations
'admin.translations.index' => true,
'admin.translations.edit' => true,
// appearance
'admin.sliders.index' => true,
'admin.sliders.create' => true,
'admin.sliders.edit' => true,
'admin.sliders.destroy' => true,
// import
'admin.importer.index' => true,
'admin.importer.create' => true,
// reports
'admin.reports.index' => true,
// settings
'admin.settings.edit' => true,
// storefront
'admin.storefront.edit' => true,
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Modules\User\Database\Seeders;
use Illuminate\Database\Seeder;
class UserDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$this->call(RolesTableSeeder::class);
$this->call(UsersTableSeeder::class);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\User\Database\Seeders;
use Illuminate\Database\Seeder;
use Modules\User\Entities\Role;
use Modules\User\Entities\User;
use Cartalyst\Sentinel\Laravel\Facades\Activation;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$adminRole = Role::find(1);
$envaySoft = User::create([
'first_name' => 'Envay',
'last_name' => 'Soft',
'email' => 'envaysoft@gmail.com',
'password' => bcrypt(123456),
]);
$activation = Activation::create($envaySoft);
Activation::complete($envaySoft, $activation->code);
$adminRole->users()->attach($envaySoft);
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace Modules\User\Entities;
use Modules\Admin\Ui\AdminTable;
use Modules\User\Repositories\Permission;
use Cartalyst\Sentinel\Roles\EloquentRole;
use Modules\Support\Eloquent\Translatable;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Role extends EloquentRole
{
use Translatable;
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = ['translations'];
/**
* The attributes that are translatable.
*
* @var array
*/
protected $translatedAttributes = ['name'];
/**
* Get a list of all roles.
*
* @return array
*/
public static function list()
{
return static::select('id')->get()->pluck('name', 'id');
}
/**
* The Users relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class, 'user_roles', 'role_id', 'user_id')->withTimestamps();
}
/**
* Set role's permissions.
*
* @param array $permissions
* @return void
*/
public function setPermissionsAttribute(array $permissions)
{
$this->attributes['permissions'] = Permission::prepare($permissions);
}
/**
* Get table data for the resource
*
* @return \Illuminate\Http\JsonResponse
*/
public function table()
{
return new AdminTable($this->newQuery());
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Modules\User\Entities;
use Modules\Support\Eloquent\TranslationModel;
class RoleTranslation extends TranslationModel
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
}

View File

@@ -0,0 +1,246 @@
<?php
namespace Modules\User\Entities;
use Modules\Order\Entities\Order;
use Modules\User\Admin\UserTable;
use Modules\Review\Entities\Review;
use Illuminate\Auth\Authenticatable;
use Modules\Address\Entities\Address;
use Modules\Product\Entities\Product;
use Modules\User\Repositories\Permission;
use Cartalyst\Sentinel\Users\EloquentUser;
use Modules\Address\Entities\DefaultAddress;
use Cartalyst\Sentinel\Laravel\Facades\Activation;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
class User extends EloquentUser implements AuthenticatableContract
{
use Authenticatable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'email',
'phone',
'password',
'last_name',
'first_name',
'permissions',
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = ['last_login'];
public static function registered($email)
{
return static::where('email', $email)->exists();
}
public static function findByEmail($email)
{
return static::where('email', $email)->first();
}
public static function totalCustomers()
{
return Role::findOrNew(setting('customer_role'))->users()->count();
}
/**
* Login the user.
*
* @return $this|bool
*/
public function login()
{
return auth()->login($this);
}
/**
* Determine if the user is a customer.
*
* @return bool
*/
public function isCustomer()
{
if ($this->hasRoleName('admin')) {
return false;
}
return $this->hasRoleId(setting('customer_role'));
}
/**
* Checks if a user belongs to the given Role ID.
*
* @param int $roleId
* @return bool
*/
public function hasRoleId($roleId)
{
return $this->roles()->whereId($roleId)->count() !== 0;
}
/**
* Checks if a user belongs to the given Role Name.
*
* @param string $name
* @return bool
*/
public function hasRoleName($name)
{
return $this->roles()->whereTranslation('name', $name)->count() !== 0;
}
/**
* Check if the current user is activated.
*
* @return bool
*/
public function isActivated()
{
return Activation::completed($this);
}
/**
* Get the recent orders of the user.
*
* @param int $take
* @return \Illuminate\Database\Eloquent\Collection
*/
public function recentOrders($take)
{
return $this->orders()->latest()->take($take)->get();
}
/**
* Get the roles of the user.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class, 'user_roles')->withTimestamps();
}
/**
* Get the orders of the user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function orders()
{
return $this->hasMany(Order::class, 'customer_id');
}
/**
* Get the wishlist of the user.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function wishlist()
{
return $this->belongsToMany(Product::class, 'wish_lists')->withTimestamps();
}
/**
* Get the default address of the user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function defaultAddress()
{
return $this->hasOne(DefaultAddress::class, 'customer_id')->withDefault();
}
/**
* Get the addresses of the user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function addresses()
{
return $this->hasMany(Address::class, 'customer_id');
}
/**
* Get the reviews of the user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function reviews()
{
return $this->hasMany(Review::class, 'reviewer_id');
}
/**
* Get the full name of the user.
*
* @return string
*/
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
/**
* Set user's permissions.
*
* @param array $permissions
* @return void
*/
public function setPermissionsAttribute(array $permissions)
{
$this->attributes['permissions'] = Permission::prepare($permissions);
}
/**
* Determine if the user has access to the given permissions.
*
* @param array|string $permissions
* @return bool
*/
public function hasAccess($permissions)
{
$permissions = is_array($permissions) ? $permissions : func_get_args();
return $this->getPermissionsInstance()->hasAccess($permissions);
}
/**
* Determine if the user has access to the any given permissions
*
* @param array|string $permissions
* @return bool
*/
public function hasAnyAccess($permissions)
{
$permissions = is_array($permissions) ? $permissions : func_get_args();
return $this->getPermissionsInstance()->hasAnyAccess($permissions);
}
public function wishlistHas($productId)
{
return self::wishlist()->where('product_id', $productId)->exists();
}
/**
* Get table data for the resource
*
* @return \Illuminate\Http\JsonResponse
*/
public function table()
{
return new UserTable($this->newQuery());
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Modules\User\Events;
use Modules\User\Entities\User;
use Illuminate\Queue\SerializesModels;
class CustomerRegistered
{
use SerializesModels;
/**
* The instance of user.
*
* @var \Modules\User\Entities\User
*/
public $user;
/**
* Create a new event instance.
*
* @param \Modules\User\Entities\User $user
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Events;
use Modules\User\Entities\User;
use Illuminate\Queue\SerializesModels;
class UserHasActivatedAccount
{
use SerializesModels;
/**
* The user instance.
*
* @var \Modules\User\Entities\User
*/
public $user;
/**
* Create a new event instance.
*
* @param \Modules\User\Entities\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Events;
use Modules\User\Entities\User;
use Illuminate\Queue\SerializesModels;
class UserHasRegistered
{
use SerializesModels;
/**
* The user instance.
*
* @var \Modules\User\Entities\User
*/
public $user;
/**
* Create a new event instance.
*
* @param \Modules\User\Entities\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace Modules\User\Guards;
use Modules\User\Entities\User;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Authenticatable;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel as SentinelFacade;
class Sentinel implements Guard
{
/**
* Determine if the current user is authenticated.
*
* @return \Modules\User\Entities\User|bool
*/
public function check()
{
return SentinelFacade::check();
}
/**
* Determine if the current user is a guest.
*
* @return \Modules\User\Entities\User|bool
*/
public function guest()
{
return SentinelFacade::guest();
}
/**
* Get the currently authenticated user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
return SentinelFacade::getUser();
}
/**
* Get the ID for the currently authenticated user.
*
* @return int|null
*/
public function id()
{
if ($user = SentinelFacade::check()) {
return $user->id;
}
return null;
}
/**
* Validate a user's credentials.
*
* @param array $credentials
* @return bool
*/
public function validate(array $credentials = [])
{
return SentinelFacade::validForCreation($credentials);
}
/**
* Set the current user.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param \Modules\User\Entities\User|bool
*/
public function setUser(Authenticatable $user)
{
return SentinelFacade::login($user);
}
/**
* Alias to set the current user.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @return \Modules\User\Entities\User|bool
*/
public function login(Authenticatable $user)
{
return $this->setUser($user);
}
/**
* Attempt to logging in user.
*
* @param array $credentials
* @param bool $remember
* @return \Modules\User\Entities\User|bool
*/
public function attempt(array $credentials, $remember = false)
{
return SentinelFacade::authenticate($credentials, $remember);
}
/**
* Logout user.
*
* @return bool
*/
public function logout()
{
return SentinelFacade::logout();
}
/**
* Login using user id.
*
* @param int $userId
* @return \Modules\User\Entities\User|bool
*/
public function loginUsingId($userId)
{
$user = User::findOrFail($userId);
return $this->login($user);
}
public function hasUser()
{
// TODO: Implement hasUser() method.
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Modules\User\Http\Controllers\BaseAuthController;
class AuthController extends BaseAuthController
{
/**
* Where to redirect users after login..
*
* @return string
*/
protected function redirectTo()
{
return route('admin.dashboard.index');
}
/**
* The login URL.
*
* @return string
*/
protected function loginUrl()
{
return route('admin.login');
}
/**
* Show login form.
*
* @return \Illuminate\Http\Response
*/
public function getLogin()
{
return view('user::admin.auth.login');
}
/**
* Show reset password form.
*
* @return \Illuminate\Http\Response
*/
public function getReset()
{
return view('user::admin.auth.reset.begin');
}
/**
* Reset complete form route.
*
* @param \Modules\User\Entities\User $user
* @param string $code
* @return string
*/
protected function resetCompleteRoute($user, $code)
{
return route('admin.reset.complete', [$user->email, $code]);
}
/**
* Password reset complete view.
*
* @return string
*/
protected function resetCompleteView()
{
return view('user::admin.auth.reset.complete');
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Modules\Admin\Ui\Facades\TabManager;
use Modules\User\Http\Requests\UpdateProfileRequest;
class ProfileController
{
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit()
{
$tabs = TabManager::get('profile');
return view('user::admin.profile.edit', compact('tabs'));
}
/**
* Update the specified resource in storage.
*
* @param \Modules\User\Http\Requests\UpdateProfileRequest $request
* @return \Illuminate\Http\Response
*/
public function update(UpdateProfileRequest $request)
{
$this->bcryptPassword($request);
auth()->user()->update($request->all());
return back()->withSuccess(trans('admin::messages.resource_saved', [
'resource' => trans('user::users.profile'),
]));
}
/**
* Bcrypt user password.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
private function bcryptPassword($request)
{
if ($request->filled('password')) {
return $request->merge(['password' => bcrypt($request->password)]);
}
unset($request['password']);
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Modules\User\Entities\Role;
use Modules\Admin\Traits\HasCrudActions;
use Modules\User\Http\Requests\SaveRoleRequest;
class RoleController
{
use HasCrudActions;
/**
* Model for the resource.
*
* @var string
*/
protected $model = Role::class;
/**
* Label of the resource.
*
* @var string
*/
protected $label = 'user::roles.role';
/**
* View path of the resource.
*
* @var string
*/
protected $viewPath = 'user::admin.roles';
/**
* Form requests for the resource.
*
* @var array|string
*/
protected $validation = SaveRoleRequest::class;
}

View File

@@ -0,0 +1,94 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Modules\User\Entities\User;
use Modules\Admin\Traits\HasCrudActions;
use Modules\User\Http\Requests\SaveUserRequest;
use Cartalyst\Sentinel\Laravel\Facades\Activation;
class UserController
{
use HasCrudActions;
/**
* Model for the resource.
*
* @var string
*/
protected $model = User::class;
/**
* Label of the resource.
*
* @var string
*/
protected $label = 'user::users.user';
/**
* View path of the resource.
*
* @var string
*/
protected $viewPath = 'user::admin.users';
/**
* Form requests for the resource.
*
* @var array|string
*/
protected $validation = SaveUserRequest::class;
/**
* Store a newly created resource in storage.
*
* @param \Modules\User\Http\Requests\SaveUserRequest $request
* @return \Illuminate\Http\Response
*/
public function store(SaveUserRequest $request)
{
$request->merge(['password' => bcrypt($request->password)]);
$user = User::create($request->all());
$user->roles()->attach($request->roles);
Activation::complete($user, Activation::create($user)->code);
return redirect()->route('admin.users.index')
->withSuccess(trans('admin::messages.resource_saved', ['resource' => trans('user::users.user')]));
}
/**
* Update the specified resource in storage.
*
* @param int $id
* @param \Modules\User\Http\Requests\SaveUserRequest $request
* @return \Illuminate\Http\Response
*/
public function update($id, SaveUserRequest $request)
{
$user = User::findOrFail($id);
if (is_null($request->password)) {
unset($request['password']);
} else {
$request->merge(['password' => bcrypt($request->password)]);
}
$user->update($request->all());
$user->roles()->sync($request->roles);
if (! Activation::completed($user) && $request->activated === '1') {
Activation::complete($user, Activation::create($user)->code);
}
if (Activation::completed($user) && $request->activated === '0') {
Activation::remove($user);
}
return redirect()->route('admin.users.index')
->withSuccess(trans('admin::messages.resource_saved', ['resource' => trans('user::users.user')]));
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Modules\User\Entities\User;
use Illuminate\Support\Facades\Mail;
use Modules\User\Mail\ResetPasswordEmail;
use Modules\User\Contracts\Authentication;
class UserResetPasswordController
{
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store($id, Authentication $auth)
{
$user = User::findOrFail($id);
$code = $auth->createReminderCode($user);
Mail::to($user)
->send(new ResetPasswordEmail($user, $this->getResetCompleteURL($user, $code)));
return redirect()->route('admin.users.index')
->withSuccess(trans('user::messages.users.reset_password_email_sent'));
}
private function getResetCompleteURL($user, $code)
{
return route('admin.reset.complete', [$user->email, $code]);
}
}

View File

@@ -0,0 +1,165 @@
<?php
namespace Modules\User\Http\Controllers;
use Exception;
use Modules\Page\Entities\Page;
use Modules\User\Entities\User;
use Modules\User\LoginProvider;
use Illuminate\Support\Facades\Cache;
use Laravel\Socialite\Facades\Socialite;
class AuthController extends BaseAuthController
{
/**
* Where to redirect users after login..
*
* @return string
*/
protected function redirectTo()
{
return route('account.dashboard.index');
}
/**
* The login URL.
*
* @return string
*/
protected function loginUrl()
{
return route('login');
}
/**
* Show login form.
*
* @return \Illuminate\Http\Response
*/
public function getLogin()
{
return view('public.auth.login', [
'providers' => LoginProvider::enabled(),
]);
}
/**
* Redirect the user to the given provider authentication page.
*
* @param string $provider
* @return \Illuminate\Http\Response
*/
public function redirectToProvider($provider)
{
if (! LoginProvider::isEnable($provider)) {
abort(404);
}
return Socialite::driver($provider)->redirect();
}
/**
* Obtain the user information from the given provider.
*
* @param string $provider
* @return \Illuminate\Http\Response
*/
public function handleProviderCallback($provider)
{
if (! LoginProvider::isEnable($provider)) {
abort(404);
}
try {
$user = Socialite::driver($provider)->user();
} catch (Exception $e) {
return redirect()->route('login')->with('error', $e->getMessage());
}
if (User::registered($user->getEmail())) {
auth()->login(
User::findByEmail($user->getEmail())
);
return redirect($this->redirectTo());
}
[$firstName, $lastName] = $this->extractName($user->getName());
$registeredUser = $this->auth->registerAndActivate([
'first_name' => $firstName,
'last_name' => $lastName,
'email' => $user->getEmail(),
'phone' => '',
'password' => str_random(),
]);
$this->assignCustomerRole($registeredUser);
auth()->login($registeredUser);
return redirect($this->redirectTo());
}
private function extractName($name)
{
return explode(' ', $name, 2);
}
/**
* Show registrations form.
*
* @return \Illuminate\Http\Response
*/
public function getRegister()
{
return view('public.auth.register', [
'privacyPageUrl' => $this->getPrivacyPageUrl(),
'providers' => LoginProvider::enabled(),
]);
}
/**
* Get privacy page url.
*
* @return string
*/
private function getPrivacyPageUrl()
{
return Cache::tags('settings')->rememberForever('privacy_page_url', function () {
return Page::urlForPage(setting('storefront_privacy_page'));
});
}
/**
* Show reset password form.
*
* @return \Illuminate\Http\Response
*/
public function getReset()
{
return view('public.auth.reset.begin');
}
/**
* Reset complete form route.
*
* @param \Modules\User\Entities\User $user
* @param string $code
* @return string
*/
protected function resetCompleteRoute($user, $code)
{
return route('reset.complete', [$user->email, $code]);
}
/**
* Password reset complete view.
*
* @return string
*/
protected function resetCompleteView()
{
return view('public.auth.reset.complete');
}
}

View File

@@ -0,0 +1,232 @@
<?php
namespace Modules\User\Http\Controllers;
use Modules\User\Entities\Role;
use Modules\User\Entities\User;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Mail;
use Modules\User\Mail\ResetPasswordEmail;
use Modules\User\Contracts\Authentication;
use Modules\User\Events\CustomerRegistered;
use Modules\User\Http\Requests\LoginRequest;
use Modules\User\Http\Requests\RegisterRequest;
use Modules\User\Http\Requests\PasswordResetRequest;
use Modules\User\Http\Requests\ResetCompleteRequest;
use Cartalyst\Sentinel\Checkpoints\ThrottlingException;
use Cartalyst\Sentinel\Checkpoints\NotActivatedException;
abstract class BaseAuthController extends Controller
{
/**
* The Authentication instance.
*
* @var \Modules\User\Contracts\Authentication
*/
protected $auth;
/**
* @param \Modules\User\Contracts\Authentication $auth
*/
public function __construct(Authentication $auth)
{
$this->auth = $auth;
$this->middleware('guest')->except('getLogout');
}
/**
* Where to redirect users after login..
*
* @return string
*/
abstract protected function redirectTo();
/**
* The login route.
*
* @return string
*/
abstract protected function loginUrl();
/**
* Show login form.
*
* @return \Illuminate\Http\Response
*/
abstract public function getLogin();
/**
* Show reset password form.
*
* @return \Illuminate\Http\Response
*/
abstract public function getReset();
/**
* Login a user.
*
* @param \Modules\User\Http\Requests\LoginRequest $request
* @return \Illuminate\Http\Response
*/
public function postLogin(LoginRequest $request)
{
try {
$loggedIn = $this->auth->login([
'email' => $request->email,
'password' => $request->password,
], (bool) $request->get('remember_me', false));
if (! $loggedIn) {
return back()->withInput()
->withError(trans('user::messages.users.invalid_credentials'));
}
return redirect()->intended($this->redirectTo());
} catch (NotActivatedException $e) {
return back()->withInput()
->withError(trans('user::messages.users.account_not_activated'));
} catch (ThrottlingException $e) {
return back()->withInput()
->withError(trans('user::messages.users.account_is_blocked', ['delay' => $e->getDelay()]));
}
}
/**
* Logout current user.
*
* @return void
*/
public function getLogout()
{
$this->auth->logout();
return redirect($this->loginUrl());
}
/**
* Register a user.
*
* @param \Modules\User\Http\Requests\RegisterRequest $request
* @return \Illuminate\Http\Response
*/
public function postRegister(RegisterRequest $request)
{
$user = $this->auth->registerAndActivate($request->only([
'first_name',
'last_name',
'email',
'phone',
'password',
]));
$this->assignCustomerRole($user);
event(new CustomerRegistered($user));
return redirect($this->loginUrl())
->withSuccess(trans('user::messages.users.account_created'));
}
protected function assignCustomerRole($user)
{
$role = Role::findOrNew(setting('customer_role'));
if ($role->exists) {
$this->auth->assignRole($user, $role);
}
}
/**
* Start the reset password process.
*
* @param \Modules\User\Http\Requests\PasswordResetRequest $request
* @return \Illuminate\Http\Response
*/
public function postReset(PasswordResetRequest $request)
{
$user = User::where('email', $request->email)->first();
if (is_null($user)) {
return back()->withInput()
->withError(trans('user::messages.users.no_user_found'));
}
$code = $this->auth->createReminderCode($user);
Mail::to($user)
->send(new ResetPasswordEmail($user, $this->resetCompleteRoute($user, $code)));
return back()->withSuccess(trans('user::messages.users.check_email_to_reset_password'));
}
/**
* Reset complete form route.
*
* @param \Modules\User\Entities\User $user
* @param string $code
* @return string
*/
abstract protected function resetCompleteRoute($user, $code);
/**
* Password reset complete view.
*
* @return string
*/
abstract protected function resetCompleteView();
/**
* Show reset password complete form.
*
* @param string $email
* @param string $code
* @return \Illuminate\Http\Response
*/
public function getResetComplete($email, $code)
{
$user = User::where('email', $email)->firstOrFail();
if ($this->invalidResetCode($user, $code)) {
return redirect()->route('reset')
->withError(trans('user::messages.users.invalid_reset_code'));
}
return $this->resetCompleteView()->with(compact('user', 'code'));
}
/**
* Determine the given reset code is invalid.
*
* @param \Modules\User\Entities\User $user
* @param string $code
* @return bool
*/
private function invalidResetCode($user, $code)
{
return $user->reminders()->where('code', $code)->doesntExist();
}
/**
* Complete the reset password process.
*
* @param string $email
* @param string $code
* @param \Modules\User\Http\Requests\ResetCompleteRequest $request
* @return \Illuminate\Http\Response
*/
public function postResetComplete($email, $code, ResetCompleteRequest $request)
{
$user = User::where('email', $email)->firstOrFail();
$completed = $this->auth->completeResetPassword($user, $code, $request->new_password);
if (! $completed) {
return back()->withInput()
->withError(trans('user::messages.users.invalid_reset_code'));
}
return redirect($this->loginUrl())
->withSuccess(trans('user::messages.users.password_has_been_reset'));
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Http\Requests;
use Modules\Core\Http\Requests\Request;
class LoginRequest extends Request
{
/**
* Available attributes for users.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.users';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => 'required|email',
'password' => 'required',
];
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\User\Http\Requests;
use Modules\Core\Http\Requests\Request;
class PasswordResetRequest extends Request
{
/**
* Available attributes.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.users';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => 'required|email',
];
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\User\Http\Requests;
use Modules\Core\Http\Requests\Request;
class RegisterRequest extends Request
{
/**
* Available attributes.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.users';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'first_name' => ['required'],
'last_name' => ['required'],
'email' => ['required', 'email', 'unique:users'],
'phone' => ['required'],
'password' => ['required', 'confirmed', 'min:6'],
'captcha' => ['required', 'captcha'],
'privacy_policy' => ['accepted'],
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Http\Requests;
use Modules\Core\Http\Requests\Request;
class ResetCompleteRequest extends Request
{
/**
* Available attributes.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.users';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'new_password' => 'required|confirmed|min:6',
'new_password_confirmation' => 'required',
];
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\User\Http\Requests;
use Modules\Core\Http\Requests\Request;
class SaveRoleRequest extends Request
{
/**
* Available attributes.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.roles';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
];
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Validation\Rule;
use Modules\Core\Http\Requests\Request;
class SaveUserRequest extends Request
{
/**
* Available attributes.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.users';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'first_name' => 'required',
'last_name' => 'required',
'email' => ['required', 'email', $this->emailUniqueRule()],
'phone' => ['required'],
'password' => 'nullable|confirmed|min:6',
'roles' => ['required', Rule::exists('roles', 'id')],
];
}
private function emailUniqueRule()
{
$rule = Rule::unique('users');
if ($this->route()->getName() === 'admin.users.update') {
$userId = $this->route()->parameter('id');
return $rule->ignore($userId);
}
return $rule;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Validation\Rule;
use Modules\Core\Http\Requests\Request;
class UpdateProfileRequest extends Request
{
/**
* Available attributes.
*
* @var string
*/
protected $availableAttributes = 'user::attributes.users';
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => ['required', Rule::unique('users')->ignore($this->email, 'email')],
'phone' => ['required'],
'first_name' => ['required'],
'last_name' => ['required'],
'password' => ['nullable', 'confirmed', 'min:6'],
];
}
/**
* Hash the user password against the bcrypt algorithm.
*
* @return $this|null
*/
public function bcryptPassword()
{
if ($this->filled('password')) {
return $this->merge(['password' => bcrypt($this->password)]);
}
unset($this['password']);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Modules\User\Http\ViewComposers;
class CurrentUserComposer
{
/**
* Bind data to the view.
*
* @param \Illuminate\View\View $view
* @return void
*/
public function compose($view)
{
$view->with('currentUser', auth()->user());
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Modules\User\Listeners;
use Swift_TransportException;
use Modules\User\Mail\Welcome;
use Illuminate\Support\Facades\Mail;
use Modules\User\Events\CustomerRegistered;
class SendWelcomeEmail
{
/**
* Handle the event.
*
* @param \Modules\User\Events\CustomerRegistered $event
* @return void
*/
public function handle(CustomerRegistered $event)
{
try {
if (! setting('welcome_email')) {
return;
}
Mail::to($event->user->email)
->send(new Welcome($event->user->first_name));
} catch (Swift_TransportException $e) {
//
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Modules\User\Listeners;
use Modules\Sms\Sms;
use Modules\User\Entities\User;
use Modules\Sms\Exceptions\SmsException;
use Modules\User\Events\CustomerRegistered;
class SendWelcomeSms
{
/**
* Handle the event.
*
* @param \Modules\User\Events\CustomerRegistered $event
* @return void
*/
public function handle(CustomerRegistered $event)
{
try {
if (! setting('welcome_sms')) {
return;
}
Sms::send(
$event->user->phone,
$this->message($event->user)
);
} catch (SmsException $e) {
//
}
}
private function message(User $user)
{
return trans('sms::messages.welcome', ['first_name' => $user->first_name]);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\User;
class LoginProvider
{
private static $providers = ['facebook', 'google'];
public static function add($provider)
{
array_push(self::$providers, $provider);
return self::$providers;
}
public static function all()
{
return self::$providers;
}
public static function enabled()
{
return array_filter(self::$providers, function ($provider) {
return setting("{$provider}_login_enabled");
});
}
public static function isEnable($provider)
{
return in_array($provider, self::enabled());
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Modules\User\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Modules\Media\Entities\File;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ResetPasswordEmail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* The user entity.
*
* @var \Modules\User\Entities\User
*/
public $user;
/**
* Reset complete form url.
*
* @var string
*/
public $url;
/**
* Create a new instance.
*
* @param \Modules\User\Entities\User $user
* @param string $url
*
* @return void
*/
public function __construct($user, $url)
{
$this->user = $user;
$this->url = $url;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject(trans('user::mail.reset_your_account_password'))
->view("emails.{$this->getViewName()}", [
'logo' => File::findOrNew(setting('storefront_mail_logo'))->path,
]);
}
private function getViewName()
{
return 'reset_password' . (is_rtl() ? '_rtl' : '');
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Modules\User\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Modules\Media\Entities\File;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class Welcome extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
private $firstName;
public $heading;
public $text;
/**
* Create a new instance.
*
* @param string $firstName
* @return void
*/
public function __construct($firstName)
{
$this->firstName = $firstName;
$this->heading = trans('user::mail.welcome', ['name' => $firstName]);
$this->text = trans('user::mail.account_created');
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject(trans('user::mail.welcome', ['name' => $this->firstName]))
->view("emails.{$this->getViewName()}", [
'logo' => File::findOrNew(setting('storefront_mail_logo'))->path,
]);
}
private function getViewName()
{
return 'text' . (is_rtl() ? '_rtl' : '');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\User\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
\Modules\User\Events\CustomerRegistered::class => [
\Modules\User\Listeners\SendWelcomeEmail::class,
\Modules\User\Listeners\SendWelcomeSms::class,
],
];
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Modules\User\Providers;
use Illuminate\Support\ServiceProvider;
class SocialLoginServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (! config('app.installed')) {
return;
}
$this->setupFacebook();
$this->setupGoogle();
}
private function setupFacebook()
{
$this->app['config']->set('services.facebook', [
'client_id' => setting('facebook_login_app_id'),
'client_secret' => setting('facebook_login_app_secret'),
'redirect' => url('login/facebook/callback'),
]);
}
private function setupGoogle()
{
$this->app['config']->set('services.google', [
'client_id' => setting('google_login_client_id'),
'client_secret' => setting('google_login_client_secret'),
'redirect' => url('login/google/callback'),
]);
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace Modules\User\Providers;
use Modules\User\Admin\RoleTabs;
use Modules\User\Admin\UserTabs;
use Modules\User\Guards\Sentinel;
use Modules\User\Admin\ProfileTabs;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Blade;
use Modules\Support\Traits\AddsAsset;
use Illuminate\Support\ServiceProvider;
use Modules\Admin\Ui\Facades\TabManager;
use Modules\User\Contracts\Authentication;
use Modules\User\Sentinel\SentinelAuthentication;
use Modules\Admin\Http\ViewComposers\AssetsComposer;
use Modules\User\Http\ViewComposers\CurrentUserComposer;
class UserServiceProvider extends ServiceProvider
{
use AddsAsset;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (! config('app.installed')) {
return;
}
TabManager::register('users', UserTabs::class);
TabManager::register('roles', RoleTabs::class);
TabManager::register('profile', ProfileTabs::class);
View::composer('*', CurrentUserComposer::class);
View::composer('user::admin.auth.layout', AssetsComposer::class);
$this->addAdminAssets('admin.(login|reset).*', ['admin.login.css', 'admin.login.js']);
$this->addAdminAssets('admin.(users|roles).(create|edit)', ['admin.user.css', 'admin.user.js']);
$this->registerSentinelGuard();
$this->registerBladeDirectives();
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->bind(Authentication::class, SentinelAuthentication::class);
}
/**
* Register sentinel guard.
*
* @return void
*/
private function registerSentinelGuard()
{
Auth::extend('sentinel', function () {
return new Sentinel;
});
}
/**
* Register blade directives.
*
* @return void
*/
private function registerBladeDirectives()
{
Blade::directive('hasAccess', function ($permissions) {
return "<?php if (\$currentUser->hasAccess($permissions)) : ?>";
});
Blade::directive('endHasAccess', function () {
return '<?php endif; ?>';
});
Blade::directive('hasAnyAccess', function ($permissions) {
return "<?php if (\$currentUser->hasAnyAccess($permissions)) : ?>";
});
Blade::directive('endHasAnyAccess', function () {
return '<?php endif; ?>';
});
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace Modules\User\Repositories;
use Nwidart\Modules\Facades\Module;
class Permission
{
/**
* Get the permissions from all the enabled modules.
*
* @return array
*/
public static function all()
{
return static::getEnabledModulePermissions() + static::getActiveThemePermissions();
}
/**
* Get enabled module permissions.
*
* @return array
*/
private static function getEnabledModulePermissions()
{
$permissions = [];
foreach (Module::allEnabled() as $module) {
$config = config('fleetcart.modules.' . strtolower($module->getName()) . '.permissions');
if (! is_null($config)) {
$permissions[$module->getName()] = $config;
}
}
return $permissions;
}
/**
* Get active theme permissions.
*
* @return array
*/
private static function getActiveThemePermissions()
{
$permissions = config('fleetcart.themes.' . strtolower(setting('active_theme')) . '.permissions');
if (is_null($permissions)) {
return [];
}
return [setting('active_theme') => $permissions];
}
/**
* Prepare given permissions.
*
* @param array $permissions
* @return string
*/
public static function prepare(array $permissions)
{
$preparedPermissions = [];
foreach ($permissions as $name => $value) {
if (is_null($value) || is_bool($value)) {
$preparedPermissions[$name] = $value;
continue;
}
if (! is_null(static::value($value))) {
$preparedPermissions[$name] = static::value($value);
}
}
return json_encode($preparedPermissions);
}
/**
* Get the permission value.
*
* @param $permission
* @return bool|null
*/
protected static function value($permission)
{
if ($permission === '1') {
return true;
}
if ($permission === '-1') {
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
$('[data-loading]').on('click', (e) => {
let button = $(e.currentTarget);
if (button.is('i')) {
button = button.parent();
}
button.data('loading-text', button.html())
.addClass('btn-loading')
.button('loading');
});

View File

@@ -0,0 +1,21 @@
window.admin.removeSubmitButtonOffsetOn('#permissions');
$('.permission-parent-actions > .allow-all, .permission-parent-actions > .deny-all, .permission-parent-actions > .inherit-all').on('click', (e) => {
let action = e.currentTarget.className.split(/\s+/)[2].split(/-/)[0];
$(`.permission-${action}`).prop('checked', true);
});
$('.permission-group-actions > .allow-all, .permission-group-actions > .deny-all, .permission-group-actions > .inherit-all').on('click', (e) => {
let action = e.currentTarget.className.split(/\s+/)[2].split(/-/)[0];
$(e.currentTarget).closest('.permission-group')
.find(`.permission-${action}`)
.each((index, value) => {
$(value).prop('checked', true);
});
});
$('.delete-api-key').on('click', (e) => {
$('#confirmation-form').attr('action', e.currentTarget.dataset.action);
});

View File

@@ -0,0 +1,147 @@
/* resets */
h1, h2, h3, h4, h5, h6, p {
margin: 0;
}
body, html {
height: 100% !important;
width: 100% !important;
margin: 0;
display: table;
}
body {
font-family: "Roboto", sans-serif;
font-weight: 400;
background: #f1f3f7;
display: table-cell;
vertical-align: middle;
}
/* login page */
.login-page {
display: table;
width: 360px;
margin: auto;
}
.login-wrapper {
position: relative;
background: #ffffff;
border-radius: 3px;
padding: 15px;
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.15);
z-index: 0;
.bg-blue {
position: absolute;
left: 0;
top: 0;
right: 0;
height: 80px;
background: #0068e1;
overflow: hidden;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
z-index: -1;
.reflection {
position: absolute;
left: -105px;
top: 0;
height: 300px;
width: 300px;
background: linear-gradient(rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05));
transform: rotate(50deg);
}
}
.form-inner {
background: #ffffff;
border-radius: 3px;
border: 1px solid #e9e9e9;
margin: 15px 0 0;
padding: 0 15px 10px;
}
.reset-password {
p {
margin-bottom: 20px;
}
.login-form > button {
margin-bottom: 10px;
}
.input-icon {
top: 5px !important;
}
> a {
margin: 5px auto 5px;
}
}
h3 {
margin: 15px 0;
}
.form-group {
position: relative;
label > span {
color: #fc4b4b;
margin-left: 4px;
}
.form-control {
padding-left: 36px;
}
}
button {
display: table;
margin: 20px auto 5px;
padding-left: 60px;
padding-right: 60px;
}
a {
display: table;
margin-top: 10px;
color: #0068e1;
&:hover {
text-decoration: underline;
}
}
}
.reset-password {
button {
padding-left: 30px;
padding-right: 30px;
}
}
@media screen and (max-width: 415px) {
.login-page {
width: 100%;
margin: 0;
padding: 0 15px;
.checkbox {
float: none !important;
display: table;
margin: 10px auto 0;
}
a {
float: none !important;
display: table;
margin: 10px auto;
}
}
}

View File

@@ -0,0 +1,91 @@
.permission-row {
padding: 6px 0 4px 0;
}
.api-keys {
margin-bottom: 20px;
}
.permission-group {
margin-bottom: 30px;
}
.permission-parent-head {
margin-bottom: 15px;
h3 {
border-bottom: 1px solid #d2d6de;
padding-bottom: 5px;
}
}
%permission-actions {
border: 1px solid #d2d6de;
}
%permission-actions-btn {
padding: 3px 10px;
margin-left: 0px !important;
border-right: 1px solid #d2d6de;
&:last-child {
border-right: none;
}
}
.permission-parent-actions {
@extend %permission-actions;
margin-top: 0;
> .btn {
@extend %permission-actions-btn;
}
}
.permission-group-actions {
@extend %permission-actions;
> .btn {
@extend %permission-actions-btn;
}
}
.permission-row {
.permission-label {
font-family: "Open Sans", sans-serif;
font-weight: 600;
display: block;
padding-top: 6px;
}
.radio-btn {
.radio {
float: right;
margin-left: 15px;
&:last-child {
margin-left: 0;
}
}
}
}
#new_password {
.btn-reset-password {
margin: 10px 0 15px;
}
}
@media screen and (max-width: 767px) {
.permission-row {
.radio-btn {
float: left;
margin-left: 15px;
}
}
.permission-group-actions {
margin-top: 10px;
}
}

View File

@@ -0,0 +1,25 @@
<?php
return [
'auth' => [
'remember_me' => 'Remember me',
],
'users' => [
'first_name' => 'First Name',
'last_name' => 'Last Name',
'email' => 'Email',
'phone' => 'Phone',
'password' => 'Password',
'password_confirmation' => 'Confirm Password',
'captcha' => 'Captcha',
'roles' => 'Roles',
'activated' => 'Status',
'new_password' => 'New Password',
'confirm_new_password' => 'Confirm New Password',
],
'roles' => [
'name' => 'Name',
],
];

View File

@@ -0,0 +1,29 @@
<?php
return [
'login' => 'Login',
'logout' => 'Logout',
'email' => 'Email',
'phone' => 'Phone',
'password' => 'Password',
'remember_me' => 'Remember me',
'forgot_password' => 'forgot password?',
'sign_in' => 'SIGN IN',
'or_continue_with' => 'Or, Continue With',
'or_sign_up_with' => 'Or, Sign Up With',
'facebook' => 'Facebook',
'google' => 'Google',
'dont_have_an_account' => 'Don\'t Have an Account?',
'create_account' => 'CREATE ACCOUNT',
'register' => 'Register',
'already_have_an_account' => 'Already Have an Account?',
'first_name' => 'First Name',
'last_name' => 'Last Name',
'confirm_password' => 'Confirm Password',
'i_agree_to_the' => 'I agree to the',
'privacy_policy' => 'Privacy Policy',
'reset_password' => 'Reset Password',
'enter_email' => 'Enter your account email to receive a link allowing you to reset your password.',
'i_remembered_my_password' => 'I remembered my password',
'submit' => 'SUBMIT',
];

View File

@@ -0,0 +1,11 @@
<?php
return [
'welcome' => 'Welcome :name!',
'account_created' => 'Your account has been created successfully.',
'reset_your_account_password' => 'Reset your account password',
'received_a_password_reset_request' => 'You are receiving this email because we received a password reset request for your account.',
'reset_password' => 'Reset Password',
'no_further_action_is_required' => 'If you did not request a password reset, no further action is required.',
'if_you\re_having_trouble' => 'If youre having trouble clicking the "Reset Password" button, copy and paste the URL below into your web browser:',
];

View File

@@ -0,0 +1,18 @@
<?php
return [
'users' => [
'account_created' => 'Your account has been created.',
'no_user_found' => 'No user with that email address belongs to our system.',
'invalid_credentials' => 'Invalid email address or password.',
'account_not_activated' => 'Your account is not activated. Please check your email.',
'account_is_blocked' => 'Your account is blocked for :delay seconds.',
'check_email_to_reset_password' => 'Check your email address to reset password.',
'invalid_reset_code' => 'Invalid or expired reset code.',
'password_has_been_reset' => 'Your password has been reset.',
'reset_password_email_sent' => 'Reset password email sent.',
],
'email' => [
'reset_password' => 'Reset your account password.',
],
];

View File

@@ -0,0 +1,16 @@
<?php
return [
'users' => [
'index' => 'Index Users',
'create' => 'Create Users',
'edit' => 'Edit Users',
'destroy' => 'Delete Users',
],
'roles' => [
'index' => 'Index Roles',
'create' => 'Create Roles',
'edit' => 'Edit Roles',
'destroy' => 'Delete Roles',
],
];

View File

@@ -0,0 +1,22 @@
<?php
return [
'role' => 'Role',
'roles' => 'Roles',
'table' => [
'name' => 'Name',
],
'tabs' => [
'role_information' => 'Role Information',
'general' => 'General',
'permissions' => 'Permissions',
],
'permissions' => [
'allow_all' => 'Allow all',
'deny_all' => 'Deny all',
'inherit_all' => 'Inherit all',
'allow' => 'Allow',
'deny' => 'Deny',
'inherit' => 'Inherit',
],
];

View File

@@ -0,0 +1,6 @@
<?php
return [
'users' => 'Users',
'roles' => 'Roles',
];

View File

@@ -0,0 +1,27 @@
<?php
return [
'user' => 'User',
'users' => 'Users',
'profile' => 'Profile',
'table' => [
'first_name' => 'First Name',
'last_name' => 'Last Name',
'email' => 'Email',
'last_login' => 'Last Login',
],
'tabs' => [
'group' => [
'user_information' => 'User Information',
'profile_information' => 'Profile Information',
],
'account' => 'Account',
'permissions' => 'Permissions',
'new_password' => 'New Password',
],
'form' => [
'activated' => 'Activated',
],
'or_reset_password' => 'or, Reset Password',
'send_reset_password_email' => 'Send Reset Password Email',
];

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<base href="{{ url('/') }}">
<meta charset="UTF-8">
<title>
@yield('title') - FleetCart
</title>
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:600|Roboto:400,500" rel="stylesheet">
@foreach ($assets->allCss() as $css)
<link media="all" type="text/css" rel="stylesheet" href="{{ v($css) }}">
@endforeach
@include('admin::partials.globals')
</head>
<body class="clearfix">
<div class="login-page">
@include('admin::partials.notification')
@yield('content')
</div>
@foreach ($assets->allJs() as $js)
<script src="{{ v($js) }}"></script>
@endforeach
</body>
</html>

View File

@@ -0,0 +1,62 @@
@extends('user::admin.auth.layout')
@section('title', trans('user::auth.login'))
@section('content')
<div class="login-wrapper">
<div class="bg-blue">
<div class="reflection"></div>
</div>
<div class="form-inner clearfix">
<h3 class="text-center">{{ setting('store_name') }}</h3>
<form method="POST" action="{{ route('admin.login.post') }}">
{{ csrf_field() }}
<div class="form-group">
<label for="email">{{ trans('user::auth.email') }}<span>*</span></label>
<input type="text" name="email" value="{{ old('email') }}" class="form-control" id="email"
placeholder="{{ trans('user::attributes.users.email') }}" autofocus>
<div class="input-icon">
<i class="fa fa-envelope-o" aria-hidden="true"></i>
</div>
{!! $errors->first('email', '<span class="help-block text-red">:message</span>') !!}
</div>
<div class="form-group">
<label for="password">{{ trans('user::auth.password') }}<span>*</span></label>
<input type="password" class="form-control" name="password"
placeholder="{{ trans('user::attributes.users.password') }}">
<div class="input-icon">
<i class="fa fa-lock" aria-hidden="true"></i>
</div>
{!! $errors->first('password', '<span class="help-block text-red">:message</span>') !!}
</div>
<button type="submit" class="btn btn-primary" data-loading>
{{ trans('user::auth.login') }}
</button>
<div class="clearfix"></div>
<div class="checkbox pull-left">
<input type="hidden" name="remember_me" value="0">
<input type="checkbox" name="remember_me" value="1" id="remember-me">
<label for="remember-me">{{ trans('user::attributes.auth.remember_me') }}</label>
</div>
<a href="{{ route('admin.reset') }}" class="text-center pull-right">
{{ trans('user::auth.forgot_password') }}
</a>
</form>
</div>
</div>
@endsection

View File

@@ -0,0 +1,36 @@
@extends('user::admin.auth.layout')
@section('title', trans('user::auth.reset_password'))
@section('content')
<div class="login-wrapper">
<div class="bg-blue">
<div class="reflection"></div>
</div>
<div class="form-inner reset-password clearfix">
<h3 class="text-center">{{ trans('user::auth.reset_password') }}</h3>
<p class="text-center">{{ trans('user::auth.enter_email') }}</p>
<form method="POST" action="{{ route('admin.reset.post') }}">
{{ csrf_field() }}
<div class="form-group">
<input type="text" name="email" value="{{ old('email') }}" class="form-control" placeholder="{{ trans('user::attributes.users.email') }}" autofocus>
<div class="input-icon">
<i class="fa fa-envelope-o" aria-hidden="true"></i>
</div>
{!! $errors->first('email', '<span class="help-block text-red">:message</span>') !!}
</div>
<button type="submit" class="btn btn-primary" data-loading>
{{ trans('user::auth.reset_password') }}
</button>
</form>
<a class="text-center" href="{{ route('admin.login') }}">{{ trans('user::auth.i_remembered_my_password') }}</a>
</div>
</div>
@endsection

View File

@@ -0,0 +1,43 @@
@extends('user::admin.auth.layout')
@section('title', trans('user::auth.reset_password'))
@section('content')
<div class="login-wrapper">
<div class="bg-blue">
<div class="reflection"></div>
</div>
<div class="form-inner reset-password clearfix">
<h3 class="text-center">{{ trans('user::auth.reset_password') }}</h3>
<form method="POST" class="login-form clearfix">
{{ csrf_field() }}
<div class="form-group">
<input type="password" class="form-control" name="new_password" placeholder="{{ trans('user::attributes.users.new_password') }}" autofocus>
<div class="input-icon">
<i class="fa fa-lock"></i>
</div>
{!! $errors->first('new_password', '<span class="help-block text-red">:message</span>') !!}
</div>
<div class="form-group">
<input type="password" class="form-control" name="new_password_confirmation" placeholder="{{ trans('user::attributes.users.confirm_new_password') }}">
<div class="input-icon">
<i class="fa fa-lock"></i>
</div>
{!! $errors->first('new_password_confirmation', '<span class="help-block text-red">:message</span>') !!}
</div>
<button class="btn btn-primary" type="submit" data-loading>
{{ trans('user::auth.reset_password') }}
</button>
</form>
</div>
</div>
@endsection

View File

@@ -0,0 +1,38 @@
<div class="permission-row">
<div class="row">
<div class="col-md-5 col-sm-4">
<span class="permission-label">{{ trans($permissionLabel) }}</sapn>
</div>
<div class="col-md-7 col-sm-8">
<div class="row">
<div class="radio-btn clearfix">
@if (! is_null($entity))
@php
$permissionValue = old('permissions')["{$group}.{$permissionAction}"] ?? permission_value($entity->permissions ?: [], "{$group}.{$permissionAction}")
@endphp
@endif
<div class="radio">
<input type="radio" value="0" id="{{ "{$group}-{$permissionAction}" }}-inherit" name="permissions[{{ "{$group}.{$permissionAction}" }}]" class="permission-inherit" {{ isset($permissionValue) && $permissionValue == 0 ? 'checked' : '' }}>
<label for="{{ "{$group}-{$permissionAction}" }}-inherit">{{ trans('user::roles.permissions.inherit') }}</label>
</div>
<div class="radio">
<input type="radio" value="-1" id="{{ "{$group}-{$permissionAction}" }}-deny" name="permissions[{{ "{$group}.{$permissionAction}" }}]" class="permission-deny" {{ isset($permissionValue) && $permissionValue == -1 ? 'checked' : '' }}>
<label for="{{ "{$group}-{$permissionAction}" }}-deny">{{ trans('user::roles.permissions.deny') }}</label>
</div>
<div class="radio">
<input type="radio" value="1" id="{{ "{$group}-{$permissionAction}" }}-allow" name="permissions[{{ "{$group}.{$permissionAction}" }}]" class="permission-allow" {{ isset($permissionValue) && $permissionValue == 1 ? 'checked' : '' }}>
<label for="{{ "{$group}-{$permissionAction}" }}-allow">{{ trans('user::roles.permissions.allow') }}</label>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,55 @@
<div class="row">
<div class="col-lg-9 col-md-12">
<div class="btn-group permission-parent-actions pull-right">
<button type="button" class="btn btn-default allow-all">{{ trans('user::roles.permissions.allow_all')}}</button>
<button type="button" class="btn btn-default deny-all">{{ trans('user::roles.permissions.deny_all')}}</button>
<button type="button" class="btn btn-default inherit-all">{{ trans('user::roles.permissions.inherit_all')}}</button>
</div>
</div>
</div>
@foreach ($permissions as $module => $modulePermissions)
<div class="row">
<div class="col-lg-9 col-md-12">
<div class="col-md-12">
<div class="row">
<div class="permission-parent-head clearfix">
<h3>{{ $module }}</h3>
</div>
</div>
</div>
<div class="clearfix"></div>
@foreach ($modulePermissions as $group => $groupPermissions)
<div class="permission-group">
<div class="row">
<div class="col-md-12">
<div class="permission-group-head">
<div class="row">
<div class="col-md-4 col-sm-4">
<h4>{{ $group }}</h4>
</div>
<div class="col-md-8 col-sm-8">
<div class="btn-group permission-group-actions pull-right">
<button type="button" class="btn btn-default allow-all">{{ trans('user::roles.permissions.allow_all')}}</button>
<button type="button" class="btn btn-default deny-all">{{ trans('user::roles.permissions.deny_all')}}</button>
<button type="button" class="btn btn-default inherit-all">{{ trans('user::roles.permissions.inherit_all')}}</button>
</div>
</div>
</div>
</div>
<div class="col-md-12">
@foreach ($groupPermissions as $permissionAction => $permissionLabel)
@include('user::admin.partials.permissions.actions')
@endforeach
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
@endforeach

View File

@@ -0,0 +1,18 @@
@extends('admin::layout')
@section('title', trans('admin::resource.edit', ['resource' => trans('user::users.profile')]))
@component('admin::components.page.header')
@slot('title', trans('admin::resource.edit', ['resource' => trans('user::users.profile')]))
<li class="active">{{ trans('admin::resource.edit', ['resource' => trans('user::users.profile')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.profile.update') }}" class="form-horizontal" id="profile-form" novalidate>
{{ csrf_field() }}
{{ method_field('put') }}
{!! $tabs->render() !!}
</form>
@endsection

View File

@@ -0,0 +1,7 @@
<div class="row">
<div class="col-md-8">
{{ Form::text('first_name', trans('user::attributes.users.first_name'), $errors, $currentUser, ['required' => true]) }}
{{ Form::text('last_name', trans('user::attributes.users.last_name'), $errors, $currentUser, ['required' => true]) }}
{{ Form::email('email', trans('user::attributes.users.email'), $errors, $currentUser, ['required' => true]) }}
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="row">
<div class="col-md-8">
{{ Form::password('password', trans('user::attributes.users.new_password'), $errors) }}
{{ Form::password('password_confirmation', trans('user::attributes.users.confirm_new_password'), $errors) }}
</div>
</div>

View File

@@ -0,0 +1,18 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('admin::resource.create', ['resource' => trans('user::roles.role')]))
<li><a href="{{ route('admin.roles.index') }}">{{ trans('user::roles.roles') }}</a></li>
<li class="active">{{ trans('admin::resource.create', ['resource' => trans('user::roles.role')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.roles.store') }}" class="form-horizontal" id="role-create-form" novalidate>
{{ csrf_field() }}
{!! $tabs->render(compact('role')) !!}
</form>
@endsection
@include('user::admin.roles.partials.shortcuts')

View File

@@ -0,0 +1,20 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('admin::resource.edit', ['resource' => trans('user::roles.role')]))
@slot('subtitle', $role->name)
<li><a href="{{ route('admin.roles.index') }}">{{ trans('user::roles.roles') }}</a></li>
<li class="active">{{ trans('admin::resource.edit', ['resource' => trans('user::roles.role')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.roles.update', $role) }}" class="form-horizontal" id="role-edit-form" novalidate>
{{ csrf_field() }}
{{ method_field('put') }}
{!! $tabs->render(compact('role')) !!}
</form>
@endsection
@include('user::admin.roles.partials.shortcuts')

View File

@@ -0,0 +1,36 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('user::roles.roles'))
<li class="active">{{ trans('user::roles.roles') }}</li>
@endcomponent
@component('admin::components.page.index_table')
@slot('buttons', ['create'])
@slot('resource', 'roles')
@slot('name', trans('user::roles.role'))
@slot('thead')
<tr>
@include('admin::partials.table.select_all')
<th>{{ trans('admin::admin.table.id') }}</th>
<th>{{ trans('user::roles.table.name') }}</th>
<th data-sort>{{ trans('admin::admin.table.created') }}</th>
</tr>
@endslot
@endcomponent
@push('scripts')
<script>
new DataTable('#roles-table .table', {
columns: [
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
{ data: 'id', width: '5%' },
{ data: 'name', name: 'translations.name', orderable: false, defaultContent: '' },
{ data: 'created', name: 'created_at' },
]
});
</script>
@endpush

View File

@@ -0,0 +1,14 @@
@push('shortcuts')
<dl class="dl-horizontal">
<dt><code>b</code></dt>
<dd>{{ trans('user::roles.navigation.back to index') }}</dd>
</dl>
@endpush
@push('scripts')
<script>
keypressAction([
{ key: 'b', route: "{{ route('admin.roles.index') }}" },
]);
</script>
@endpush

View File

@@ -0,0 +1,5 @@
<div class="row">
<div class="col-sm-8">
{{ Form::text('name', trans('user::attributes.roles.name'), $errors, $role, ['required' => true]) }}
</div>
</div>

View File

@@ -0,0 +1,18 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('admin::resource.create', ['resource' => trans('user::users.user')]))
<li><a href="{{ route('admin.users.index') }}">{{ trans('user::users.users') }}</a></li>
<li class="active">{{ trans('admin::resource.create', ['resource' => trans('user::users.user')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.users.store') }}" class="form-horizontal" id="user-create-form" novalidate>
{{ csrf_field() }}
{!! $tabs->render(compact('user')) !!}
</form>
@endsection
@include('user::admin.users.partials.shortcuts')

View File

@@ -0,0 +1,20 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('admin::resource.edit', ['resource' => trans('user::users.user')]))
@slot('subtitle', $user->full_name)
<li><a href="{{ route('admin.users.index') }}">{{ trans('user::users.users') }}</a></li>
<li class="active">{{ trans('admin::resource.edit', ['resource' => trans('user::users.user')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.users.update', $user) }}" class="form-horizontal" id="user-edit-form" novalidate>
{{ csrf_field() }}
{{ method_field('put') }}
{!! $tabs->render(compact('user')) !!}
</form>
@endsection
@include('user::admin.users.partials.shortcuts')

View File

@@ -0,0 +1,42 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('user::users.users'))
<li class="active">{{ trans('user::users.users') }}</li>
@endcomponent
@component('admin::components.page.index_table')
@slot('buttons', ['create'])
@slot('resource', 'users')
@slot('name', trans('user::users.user'))
@slot('thead')
<tr>
@include('admin::partials.table.select_all')
<th>{{ trans('admin::admin.table.id') }}</th>
<th>{{ trans('user::users.table.first_name') }}</th>
<th>{{ trans('user::users.table.last_name') }}</th>
<th>{{ trans('user::users.table.email') }}</th>
<th>{{ trans('user::users.table.last_login') }}</th>
<th data-sort>{{ trans('admin::admin.table.created') }}</th>
</tr>
@endslot
@endcomponent
@push('scripts')
<script>
new DataTable('#users-table .table', {
columns: [
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
{ data: 'id', width: '5%' },
{ data: 'first_name', name: 'first_name' },
{ data: 'last_name', name: 'last_name' },
{ data: 'email', name: 'email' },
{ data: 'last_login', name: 'last_login', searchable: false },
{ data: 'created', name: 'created_at' },
]
});
</script>
@endpush

View File

@@ -0,0 +1,14 @@
@push('shortcuts')
<dl class="dl-horizontal">
<dt><code>b</code></dt>
<dd>{{ trans('user::users.navigation.back to index') }}</dd>
</dl>
@endpush
@push('scripts')
<script>
keypressAction([
{ key: 'b', route: "{{ route('admin.users.index') }}" },
]);
</script>
@endpush

View File

@@ -0,0 +1,18 @@
<div class="row">
<div class="col-md-8">
{{ Form::text('first_name', trans('user::attributes.users.first_name'), $errors, $user, ['required' => true]) }}
{{ Form::text('last_name', trans('user::attributes.users.last_name'), $errors, $user, ['required' => true]) }}
{{ Form::email('email', trans('user::attributes.users.email'), $errors, $user, ['required' => true]) }}
{{ Form::text('phone', trans('user::attributes.users.phone'), $errors, $user, ['required' => true]) }}
{{ Form::select('roles', trans('user::attributes.users.roles'), $errors, $roles, $user, ['multiple' => true, 'required' => true, 'class' => 'selectize prevent-creation']) }}
@if (request()->routeIs('admin.users.create'))
{{ Form::password('password', trans('user::attributes.users.password'), $errors, null, ['required' => true]) }}
{{ Form::password('password_confirmation', trans('user::attributes.users.password_confirmation'), $errors, null, ['required' => true]) }}
@endif
@if (request()->routeIs('admin.users.edit'))
{{ Form::checkbox('activated', trans('user::attributes.users.activated'), trans('user::users.form.activated'), $errors, $user, ['disabled' => $user->id === $currentUser->id, 'checked' => old('activated', $user->isActivated())]) }}
@endif
</div>
</div>

View File

@@ -0,0 +1,14 @@
<div class="row">
<div class="col-md-8">
{{ Form::password('password', trans('user::attributes.users.new_password'), $errors) }}
{{ Form::password('password_confirmation', trans('user::attributes.users.confirm_new_password'), $errors) }}
</div>
<div class="col-md-4">
<h4>{{ trans('user::users.or_reset_password') }}</h4>
<a href="{{ route('admin.users.reset_password', $user) }}" class="btn btn-primary btn-reset-password" data-loading>
{{ trans('user::users.send_reset_password_email') }}
</a>
</div>
</div>

View File

@@ -0,0 +1,102 @@
<?php
use Illuminate\Support\Facades\Route;
Route::get('login', 'AuthController@getLogin')->name('admin.login');
Route::post('login', 'AuthController@postLogin')->name('admin.login.post');
Route::get('logout', 'AuthController@getLogout')->name('admin.logout');
Route::get('password/reset', 'AuthController@getReset')->name('admin.reset');
Route::post('password/reset', 'AuthController@postReset')->name('admin.reset.post');
Route::get('password/reset/{email}/{code}', 'AuthController@getResetComplete')->name('admin.reset.complete');
Route::post('password/reset/{email}/{code}', 'AuthController@postResetComplete')->name('admin.reset.complete.post');
Route::get('users', [
'as' => 'admin.users.index',
'uses' => 'UserController@index',
'middleware' => 'can:admin.users.index',
]);
Route::get('users/create', [
'as' => 'admin.users.create',
'uses' => 'UserController@create',
'middleware' => 'can:admin.users.create',
]);
Route::post('users', [
'as' => 'admin.users.store',
'uses' => 'UserController@store',
'middleware' => 'can:admin.users.create',
]);
Route::get('users/{id}/edit', [
'as' => 'admin.users.edit',
'uses' => 'UserController@edit',
'middleware' => 'can:admin.users.edit',
]);
Route::put('users/{id}/edit', [
'as' => 'admin.users.update',
'uses' => 'UserController@update',
'middleware' => 'can:admin.users.edit',
]);
Route::delete('users/{ids?}', [
'as' => 'admin.users.destroy',
'uses' => 'UserController@destroy',
'middleware' => 'can:admin.users.destroy',
]);
Route::get('users/{id}/reset-password', [
'as' => 'admin.users.reset_password',
'uses' => 'UserResetPasswordController@store',
'middleware' => 'can:admin.users.edit',
]);
Route::get('roles', [
'as' => 'admin.roles.index',
'uses' => 'RoleController@index',
'middleware' => 'can:admin.roles.index',
]);
Route::get('roles/create', [
'as' => 'admin.roles.create',
'uses' => 'RoleController@create',
'middleware' => 'can:admin.roles.create',
]);
Route::post('roles', [
'as' => 'admin.roles.store',
'uses' => 'RoleController@store',
'middleware' => 'can:admin.roles.create',
]);
Route::get('roles/{id}/edit', [
'as' => 'admin.roles.edit',
'uses' => 'RoleController@edit',
'middleware' => 'can:admin.roles.edit',
]);
Route::put('roles/{id}/edit', [
'as' => 'admin.roles.update',
'uses' => 'RoleController@update',
'middleware' => 'can:admin.roles.edit',
]);
Route::delete('roles/{ids?}', [
'as' => 'admin.roles.destroy',
'uses' => 'RoleController@destroy',
'middleware' => 'can:admin.roles.destroy',
]);
// Profile
Route::get('profile', [
'as' => 'admin.profile.edit',
'uses' => 'ProfileController@edit',
]);
Route::put('profile', [
'as' => 'admin.profile.update',
'uses' => 'ProfileController@update',
]);

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Support\Facades\Route;
use Spatie\Honeypot\ProtectAgainstSpam;
Route::get('login', 'AuthController@getLogin')->name('login');
Route::post('login', 'AuthController@postLogin')->name('login.post');
Route::get('login/{provider}', 'AuthController@redirectToProvider')->name('login.redirect');
Route::get('login/{provider}/callback', 'AuthController@handleProviderCallback')->name('login.callback');
Route::get('logout', 'AuthController@getLogout')->name('logout');
Route::get('register', 'AuthController@getRegister')->name('register');
Route::post('register', 'AuthController@postRegister')
->name('register.post')
->middleware(ProtectAgainstSpam::class);
Route::get('password/reset', 'AuthController@getReset')->name('reset');
Route::post('password/reset', 'AuthController@postReset')->name('reset.post');
Route::get('password/reset/{email}/{code}', 'AuthController@getResetComplete')->name('reset.complete');
Route::post('password/reset/{email}/{code}', 'AuthController@postResetComplete')->name('reset.complete.post');

View File

@@ -0,0 +1,185 @@
<?php
namespace Modules\User\Sentinel;
use Modules\User\Entities\Role;
use Modules\User\Entities\User;
use Modules\User\Contracts\Authentication;
use Cartalyst\Sentinel\Laravel\Facades\Reminder;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Modules\User\Events\UserHasActivatedAccount;
use Cartalyst\Sentinel\Laravel\Facades\Activation;
class SentinelAuthentication implements Authentication
{
/**
* Authenticate a user.
*
* @param array $credentials
* @param bool $remember
* @return mixed
*/
public function login($credentials, $remember = false)
{
return Sentinel::authenticate($credentials, $remember);
}
/**
* Register a new user.
*
* @param array $data
* @return bool
*/
public function register($data)
{
return Sentinel::register($data);
}
/**
* Register and activate a new user.
*
* @param array $data
* @return \Modules\User\Entities\User
*/
public function registerAndActivate($data)
{
return Sentinel::registerAndActivate($data);
}
/**
* Activate the given used id.
*
* @param int $userId
* @param string $code
* @return void
*/
public function activate($userId, $code)
{
$user = Sentinel::findById($userId);
if (Activation::complete($user, $code)) {
event(new UserHasActivatedAccount($user));
}
}
/**
* Assign a role to the given user.
*
* @param \Modules\User\Entities\User $user
* @param \Modules\User\Entities\Role $role
* @return void
*/
public function assignRole(User $user, Role $role)
{
$role->users()->attach($user);
}
/**
* Log the user out of the application.
*
* @return bool
*/
public function logout()
{
return Sentinel::logout();
}
/**
* Create an activation code for the given user.
*
* @param \Modules\User\Entities\User $user
* @return \Cartalyst\Sentinel\Activations\ActivationInterface
*/
public function createActivation(User $user)
{
return Activation::create($user)->code;
}
/**
* Create a reminders code for the given user.
*
* @param \Modules\User\Entities\User $user
* @return string
*/
public function createReminderCode(User $user)
{
return Reminder::create($user)->code;
}
/**
* Completes the reset password process.
*
* @param \Modules\User\Entities\User $user
* @param string $code
* @param string $password
* @return bool
*/
public function completeResetPassword(User $user, $code, $password)
{
return Reminder::complete($user, $code, $password);
}
/**
* Determines if the current user has access to the given permissions.
*
* @param array|string $permissions
* @return bool
*/
public function hasAccess($permissions)
{
if (Sentinel::guest()) {
return false;
}
$permissions = is_array($permissions) ? $permissions : func_get_args();
return Sentinel::hasAccess($permissions);
}
/**
* Determine if the current user has access to the any given permissions
*
* @param array|string $permissions
* @return bool
*/
public function hasAnyAccess($permissions)
{
if (Sentinel::guest()) {
return false;
}
$permissions = is_array($permissions) ? $permissions : func_get_args();
return Sentinel::hasAnyAccess($permissions);
}
/**
* Check if the user is logged in.
*
* @return bool
*/
public function check()
{
return Sentinel::check();
}
/**
* Get the currently logged in user.
*
* @return \Modules\User\Entities\User|null
*/
public function user()
{
return Sentinel::getUser();
}
/**
* Get the ID for the currently authenticated user.
*
* @return int|null
*/
public function id()
{
return optional($this->user())->id;
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Modules\User\Services;
use Modules\User\Entities\Role;
use Modules\User\Contracts\Authentication;
class CustomerService
{
private $auth;
public function __construct(Authentication $auth)
{
$this->auth = $auth;
}
public function register($request)
{
return tap($this->auth->registerAndActivate($this->getCustomerData($request)), function ($user) {
$role = Role::find(setting('customer_role'));
$user->roles()->attach($role);
});
}
private function getCustomerData($request)
{
return array_merge($request->billing, [
'email' => $request->customer_email,
'phone' => $request->customer_phone,
'password' => $request->password,
]);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Modules\User\Sidebar;
use Maatwebsite\Sidebar\Item;
use Maatwebsite\Sidebar\Menu;
use Maatwebsite\Sidebar\Group;
use Modules\Admin\Sidebar\BaseSidebarExtender;
class SidebarExtender extends BaseSidebarExtender
{
public function extend(Menu $menu)
{
$menu->group(trans('admin::sidebar.system'), function (Group $group) {
$group->item(trans('user::sidebar.users'), function (Item $item) {
$item->weight(5);
$item->icon('fa fa-users');
$item->route('admin.users.index');
$item->authorize(
$this->auth->hasAccess('admin.users.index') || $this->auth->hasAccess('roles.index')
);
// users
$item->item(trans('user::sidebar.users'), function (Item $item) {
$item->weight(5);
$item->route('admin.users.index');
$item->authorize(
$this->auth->hasAccess('admin.users.index')
);
});
// roles
$item->item(trans('user::sidebar.roles'), function (Item $item) {
$item->weight(10);
$item->route('admin.roles.index');
$item->authorize(
$this->auth->hasAccess('admin.roles.index')
);
});
});
});
}
}

View File

@@ -0,0 +1,29 @@
{
"name": "fleetcart/user",
"description": "The FleetCart User Module.",
"authors": [
{
"name": "Envay Soft",
"email": "envaysoft@gmail.com"
}
],
"require": {
"php": "^8.0.2",
"cartalyst/sentinel": "^6.0",
"laravel/socialite": "^5.0"
},
"autoload": {
"psr-4": {
"Modules\\User\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}

23
Modules/User/helpers.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
if (! function_exists('permission_value')) {
/**
* Get the integer representation value of the permission.
*
* @param array $permissions
* @param string $permission
* @return int
*/
function permission_value(array $permissions, $permission)
{
$value = array_get($permissions, $permission);
if (is_null($value)) {
return 0;
} elseif ($value) {
return 1;
} elseif (! $value) {
return -1;
}
}
}

14
Modules/User/module.json Normal file
View File

@@ -0,0 +1,14 @@
{
"name": "User",
"alias": "user",
"description": "The user module is responsible for managing users and permissions.",
"priority": 100,
"providers": [
"Modules\\User\\Providers\\UserServiceProvider",
"Modules\\User\\Providers\\EventServiceProvider",
"Modules\\User\\Providers\\SocialLoginServiceProvider"
],
"files": [
"helpers.php"
]
}

View File

@@ -0,0 +1,4 @@
{
"name": "user-module",
"private": true
}

View File

@@ -0,0 +1,11 @@
let mix = require('laravel-mix');
let execSync = require('child_process').execSync;
mix.js(`${__dirname}/Resources/assets/admin/js/main.js`, `${__dirname}/Assets/admin/js/user.js`)
.js(`${__dirname}/Resources/assets/admin/js/login.js`, `${__dirname}/Assets/admin/js/login.js`)
.sass(`${__dirname}/Resources/assets/admin/sass/login.scss`, `${__dirname}/Assets/admin/css/login.css`)
.sass(`${__dirname}/Resources/assets/admin/sass/main.scss`, `${__dirname}/Assets/admin/css/user.css`)
.then(() => {
execSync(`npm run rtlcss ${__dirname}/Assets/admin/css/login.css ${__dirname}/Assets/admin/css/login.rtl.css`);
execSync(`npm run rtlcss ${__dirname}/Assets/admin/css/user.css ${__dirname}/Assets/admin/css/user.rtl.css`);
});

29
Modules/User/yarn.lock Normal file
View File

@@ -0,0 +1,29 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
clipboard@^1.6.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b"
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
delegate@^3.1.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
dependencies:
delegate "^3.1.2"
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
tiny-emitter@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"