Added the ability to manage users.
This commit is contained in:
parent
dc6b6b0d42
commit
52c6fd88d7
10
app/Dto/Builder/User.php
Normal file
10
app/Dto/Builder/User.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Builder;
|
||||||
|
|
||||||
|
final readonly class User
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
|
||||||
|
) { }
|
||||||
|
}
|
24
app/Dto/Request/Private/User/Index.php
Normal file
24
app/Dto/Request/Private/User/Index.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Request\Private\User;
|
||||||
|
|
||||||
|
use App\Dto\Builder\User;
|
||||||
|
use App\Dto\Request\Dto;
|
||||||
|
|
||||||
|
final readonly class Index extends Dto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private User $userBuilderDto,
|
||||||
|
private int $page
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getUserBuilderDto(): User
|
||||||
|
{
|
||||||
|
return $this->userBuilderDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPage(): int
|
||||||
|
{
|
||||||
|
return $this->page;
|
||||||
|
}
|
||||||
|
}
|
42
app/Dto/Request/Private/User/StoreUpdate.php
Normal file
42
app/Dto/Request/Private/User/StoreUpdate.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Request\Private\User;
|
||||||
|
|
||||||
|
use App\Dto\Request\Dto;
|
||||||
|
use App\Dto\User\ManyRoleDto;
|
||||||
|
|
||||||
|
final readonly class StoreUpdate extends Dto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $name,
|
||||||
|
private string $email,
|
||||||
|
private bool $isActive,
|
||||||
|
private ManyRoleDto $roles,
|
||||||
|
private ?string $password = null
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEmail(): string
|
||||||
|
{
|
||||||
|
return $this->email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPassword(): ?string
|
||||||
|
{
|
||||||
|
return $this->password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRoles(): ManyRoleDto
|
||||||
|
{
|
||||||
|
return $this->roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isActive(): bool
|
||||||
|
{
|
||||||
|
return $this->isActive;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Dto\Request\Private\Profile;
|
namespace App\Dto\Request\Private\User;
|
||||||
|
|
||||||
use App\Dto\Request\Dto;
|
use App\Dto\Request\Dto;
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Enums;
|
|||||||
enum Permission: string
|
enum Permission: string
|
||||||
{
|
{
|
||||||
case Role = 'role';
|
case Role = 'role';
|
||||||
|
case User = 'user';
|
||||||
|
|
||||||
public function getPermissions(): array
|
public function getPermissions(): array
|
||||||
{
|
{
|
||||||
|
106
app/Http/Controllers/Private/UsersController.php
Normal file
106
app/Http/Controllers/Private/UsersController.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Private;
|
||||||
|
|
||||||
|
use App\Dto\QuerySettingsDto;
|
||||||
|
use App\Http\Requests\Private\Users\IndexRequest;
|
||||||
|
use App\Http\Requests\Private\Users\StoreUpdateRequest;
|
||||||
|
use App\Http\Requests\Private\Users\UpdatePasswordRequest;
|
||||||
|
use App\Services\Private\UserService;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class UsersController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UserService $userService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function index(IndexRequest $request): View
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
$data = $request->getDto();
|
||||||
|
$querySettingsDto = new QuerySettingsDto(
|
||||||
|
limit: 20,
|
||||||
|
page: $data->getPage(),
|
||||||
|
queryWith: []
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = $this->userService->index($data->getUserBuilderDto(), $querySettingsDto, $user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('private/users/index', $result->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(Request $request): View
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
$result = $this->userService->create($user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('private/users/create', $result->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(int $id, Request $request): View
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
$result = $this->userService->edit($id, $user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('private/users/edit', $result->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreUpdateRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$data = $request->getDto();
|
||||||
|
$user = $request->user();
|
||||||
|
$result = $this->userService->store($data, $user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
return redirect()->back()->withInput()->withErrors($result->getErrorsOrMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('users.edit', $result->getModel())->withSuccess($result->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(int $id, StoreUpdateRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$data = $request->getDto();
|
||||||
|
$user = $request->user();
|
||||||
|
$result = $this->userService->update($id, $data, $user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
return redirect()->back()->withInput()->withErrors($result->getErrorsOrMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('users.edit', $result->getModel())->withSuccess($result->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updatePassword(int $id, UpdatePasswordRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$data = $request->getDto();
|
||||||
|
$user = $request->user();
|
||||||
|
$result = $this->userService->updatePassword($id, $data, $user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
return redirect()->back()->withInput()->withErrors($result->getErrorsOrMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('users.edit', $result->getModel())->withSuccess($result->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $id, Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
$result = $this->userService->destroy($id, $user);
|
||||||
|
if ($result->isError()) {
|
||||||
|
return redirect()->back()->withInput()->withErrors($result->getErrorsOrMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('users.index')->withSuccess($result->getMessage());
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
namespace App\Http\Requests\Private\Profile;
|
namespace App\Http\Requests\Private\Profile;
|
||||||
|
|
||||||
use App\Contracts\FormRequestDto;
|
use App\Contracts\FormRequestDto;
|
||||||
use App\Dto\Request\Private\Profile\UpdatePassword;
|
use App\Dto\Request\Private\User\UpdatePassword;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Validation\Rules\Password;
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
|
||||||
|
30
app/Http/Requests/Private/Users/IndexRequest.php
Normal file
30
app/Http/Requests/Private/Users/IndexRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Private\Users;
|
||||||
|
|
||||||
|
use App\Contracts\FormRequestDto;
|
||||||
|
use App\Dto\Builder\User;
|
||||||
|
use App\Dto\Request\Private\User\Index;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
final class IndexRequest extends FormRequest implements FormRequestDto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$this->redirect = route('users.index');
|
||||||
|
return [
|
||||||
|
'page' => ['nullable', 'numeric', 'min:1']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDto(): Index
|
||||||
|
{
|
||||||
|
return new Index(
|
||||||
|
userBuilderDto: new User(),
|
||||||
|
page: (int) $this->input('page', 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
44
app/Http/Requests/Private/Users/StoreUpdateRequest.php
Normal file
44
app/Http/Requests/Private/Users/StoreUpdateRequest.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Private\Users;
|
||||||
|
|
||||||
|
use App\Contracts\FormRequestDto;
|
||||||
|
use App\Dto\Request\Private\User\StoreUpdate;
|
||||||
|
use App\Dto\User\ManyRoleDto;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
|
||||||
|
final class StoreUpdateRequest extends FormRequest implements FormRequestDto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'name' => ['required', 'max:255'],
|
||||||
|
'email' => ['required', 'email', 'max:255'],
|
||||||
|
'is_active' => ['required', 'boolean'],
|
||||||
|
'roles' => ['array', Rule::exists('roles', 'id')],
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->getMethod() === 'POST') {
|
||||||
|
$rules['password'] = ['required', Password::default()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getDto(): StoreUpdate
|
||||||
|
{
|
||||||
|
return new StoreUpdate(
|
||||||
|
name: $this->input('name'),
|
||||||
|
email: $this->input('email'),
|
||||||
|
isActive: (bool) $this->input('is_active', false),
|
||||||
|
roles: new ManyRoleDto($this->input('roles', [])),
|
||||||
|
password: $this->input('password', null),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
26
app/Http/Requests/Private/Users/UpdatePasswordRequest.php
Normal file
26
app/Http/Requests/Private/Users/UpdatePasswordRequest.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Private\Users;
|
||||||
|
|
||||||
|
use App\Contracts\FormRequestDto;
|
||||||
|
use App\Dto\Request\Private\User\UpdatePassword;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
|
||||||
|
final class UpdatePasswordRequest extends FormRequest implements FormRequestDto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'password' => ['required', Password::default()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDto(): UpdatePassword
|
||||||
|
{
|
||||||
|
return new UpdatePassword(password: $this->input('password'));
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@ namespace App\Models;
|
|||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
use App\Enums\Lang;
|
use App\Enums\Lang;
|
||||||
|
use App\Enums\SystemRole;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@ -66,4 +68,33 @@ final class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
return $this->belongsToMany(Role::class);
|
return $this->belongsToMany(Role::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasRole(string $role): bool
|
||||||
|
{
|
||||||
|
return $this->roles->where('code', $role)->isNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasPermission(string $permission): bool
|
||||||
|
{
|
||||||
|
return $this->permissions->search($permission) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isAdmin(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
get: fn () => $this->hasRole(SystemRole::Admin->value),
|
||||||
|
)->shouldCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function permissions(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
get: function () {
|
||||||
|
$roles = $this->roles->modelKeys();
|
||||||
|
return RolePermission::whereIn('role_id', $roles)->select('permission')->pluck('permission');
|
||||||
|
},
|
||||||
|
)->shouldCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
33
app/Policies/UserPolicy.php
Normal file
33
app/Policies/UserPolicy.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
final readonly class UserPolicy extends Policy
|
||||||
|
{
|
||||||
|
public function viewAny(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->hasPermission('user.view');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(User $user, User $userView): bool
|
||||||
|
{
|
||||||
|
return $user->hasPermission('user.view');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->hasPermission('user.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(User $user, User $userUpdate): bool
|
||||||
|
{
|
||||||
|
return $user->hasPermission('user.update');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(User $user, User $userDelete): bool
|
||||||
|
{
|
||||||
|
return $user->hasPermission('user.delete');
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,49 @@
|
|||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Contracts\Search;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Dto\Builder\User as UserBuilderDto;
|
||||||
|
use App\Services\User\BuilderCommand;
|
||||||
|
use App\Services\Search\CreateSearchInstanceCommand;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
final readonly class UserRepository
|
final readonly class UserRepository
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private CreateSearchInstanceCommand $createSearchInstanceCommand,
|
||||||
|
private BuilderCommand $builderCommand
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getUserById(int $id): ?User
|
||||||
|
{
|
||||||
|
return User::query()->where('id', $id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
public function getUserByEmail(string $email): ?User
|
public function getUserByEmail(string $email): ?User
|
||||||
{
|
{
|
||||||
return User::query()->where('email', Str::lower($email))->first();
|
return User::query()->where('email', Str::lower($email))->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUsers(UserBuilderDto $userBuilderDto, array $with = []): Search
|
||||||
|
{
|
||||||
|
$query = $this->builderCommand->execute(
|
||||||
|
query: User::query()->with($with),
|
||||||
|
userBuilderDto: $userBuilderDto
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->createSearchInstanceCommand->execute($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isExistsEmail(string $email, ?int $exceptId = null): bool
|
||||||
|
{
|
||||||
|
return User::query()
|
||||||
|
->where('email', Str::lower($email))
|
||||||
|
->when($exceptId, function (Builder $query, int $exceptId) {
|
||||||
|
$query->where('id', '!=', $exceptId);
|
||||||
|
})
|
||||||
|
->withTrashed()
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
namespace App\Services\Private;
|
namespace App\Services\Private;
|
||||||
|
|
||||||
use App\Dto\Request\Private\Profile\Update;
|
use App\Dto\Request\Private\Profile\Update;
|
||||||
use App\Dto\Request\Private\Profile\UpdatePassword;
|
|
||||||
use App\Dto\Request\Private\Profile\UpdateSettings;
|
use App\Dto\Request\Private\Profile\UpdateSettings;
|
||||||
|
use App\Dto\Request\Private\User\UpdatePassword;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\ServiceResults\ServiceResultError;
|
use App\ServiceResults\ServiceResultError;
|
||||||
use App\ServiceResults\ServiceResultSuccess;
|
use App\ServiceResults\ServiceResultSuccess;
|
||||||
|
201
app/Services/Private/UserService.php
Normal file
201
app/Services/Private/UserService.php
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services\Private;
|
||||||
|
|
||||||
|
use App\Dto\Builder\User as UserBuilderDto;
|
||||||
|
use App\Dto\Request\Private\User\StoreUpdate;
|
||||||
|
use App\Dto\Request\Private\User\UpdatePassword;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Dto\QuerySettingsDto;
|
||||||
|
use App\Repositories\RoleRepository;
|
||||||
|
use App\Repositories\UserRepository;
|
||||||
|
use App\ServiceResults\ServiceResultArray;
|
||||||
|
use App\ServiceResults\ServiceResultError;
|
||||||
|
use App\ServiceResults\ServiceResultSuccess;
|
||||||
|
use App\ServiceResults\StoreUpdateResult;
|
||||||
|
use App\Services\Service;
|
||||||
|
use App\Services\User\UserCommandHandler;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
final class UserService extends Service
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly UserRepository $userRepository,
|
||||||
|
private readonly UserCommandHandler $userCommandHandler,
|
||||||
|
private readonly RoleRepository $roleRepository
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function index(UserBuilderDto $userBuilderDto, QuerySettingsDto $querySettingsDto, User $user): ServiceResultError | ServiceResultArray
|
||||||
|
{
|
||||||
|
if ($user->cannot('viewAny', User::class)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$users = $this->userRepository->getUsers(
|
||||||
|
$userBuilderDto,
|
||||||
|
$querySettingsDto->getQueryWith()
|
||||||
|
)->pagination(
|
||||||
|
$querySettingsDto->getLimit(),
|
||||||
|
$querySettingsDto->getPage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->result([
|
||||||
|
'users' => $users,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(User $user): ServiceResultError | ServiceResultArray
|
||||||
|
{
|
||||||
|
if ($user->cannot('create', User::class)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->result([
|
||||||
|
'user' => new User(),
|
||||||
|
'roles' => $this->roleRepository->getRolesForSelect(),
|
||||||
|
'userRoles' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(int $id, User $user): ServiceResultError | ServiceResultArray
|
||||||
|
{
|
||||||
|
$modelUser = $this->userRepository->getUserById($id);
|
||||||
|
|
||||||
|
if (is_null($modelUser)) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->cannot('view', $modelUser)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$userRoles = $modelUser->roles()->withTrashed()->pluck('id')->toArray();
|
||||||
|
return $this->result([
|
||||||
|
'user' => $modelUser,
|
||||||
|
'roles' => $this->roleRepository->getRolesForSelect($userRoles),
|
||||||
|
'userRoles' => $userRoles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
|
||||||
|
{
|
||||||
|
if ($user->cannot('create', User::class)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->userRepository->isExistsEmail($data->getEmail())) {
|
||||||
|
return $this->errValidate(
|
||||||
|
__('validation.unique', ['attribute' => __('validation.attributes.email')]),
|
||||||
|
['code' => __('validation.unique', ['attribute' => __('validation.attributes.email')])]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$modelUser = DB::transaction(function () use ($data) {
|
||||||
|
$dataUser = $this->getDataUser($data);
|
||||||
|
|
||||||
|
$modelUser = $this->userCommandHandler->handleStore($dataUser, $data->getPassword());
|
||||||
|
$this->userCommandHandler->handleConfirmationByEmail($modelUser);
|
||||||
|
$this->userCommandHandler->handleSyncRoles($modelUser, $data->getRoles());
|
||||||
|
|
||||||
|
return $modelUser;
|
||||||
|
});
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
report($e);
|
||||||
|
return $this->errService(__('Server Error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->resultStoreUpdateModel($modelUser, __('The user was successfully created'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(int $id, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
|
||||||
|
{
|
||||||
|
$modelUser = $this->userRepository->getUserById($id);
|
||||||
|
|
||||||
|
if (is_null($modelUser)) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->cannot('update', $modelUser)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->userRepository->isExistsEmail($data->getEmail(), $modelUser->id)) {
|
||||||
|
return $this->errValidate(
|
||||||
|
__('validation.unique', ['attribute' => __('validation.attributes.email')]),
|
||||||
|
['code' => __('validation.unique', ['attribute' => __('validation.attributes.email')])]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$modelUser = DB::transaction(function () use ($data, $modelUser) {
|
||||||
|
$dataUser = $this->getDataUser($data);
|
||||||
|
|
||||||
|
$modelUser = $this->userCommandHandler->handleUpdate($modelUser, $dataUser);
|
||||||
|
$this->userCommandHandler->handleSyncRoles($modelUser, $data->getRoles());
|
||||||
|
|
||||||
|
return $modelUser;
|
||||||
|
});
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
report($e);
|
||||||
|
return $this->errService(__('Server Error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->resultStoreUpdateModel($modelUser, __('The user was successfully updated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updatePassword(int $id, UpdatePassword $data, User $user): ServiceResultError | StoreUpdateResult
|
||||||
|
{
|
||||||
|
$modelUser = $this->userRepository->getUserById($id);
|
||||||
|
|
||||||
|
if (is_null($modelUser)) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->cannot('update', $modelUser)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->userCommandHandler->handleUpdatePassword($modelUser, $data->getPassword());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
report($e->getMessage());
|
||||||
|
return $this->errService($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->resultStoreUpdateModel($modelUser, __('The password has been changed'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(int $id, User $user): ServiceResultError | ServiceResultSuccess
|
||||||
|
{
|
||||||
|
$modelUser = $this->userRepository->getUserById($id);
|
||||||
|
|
||||||
|
if (is_null($modelUser)) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->cannot('delete', $modelUser)) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::transaction(function () use ($modelUser) {
|
||||||
|
$this->userCommandHandler->handleDestroy($modelUser);
|
||||||
|
});
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
report($e);
|
||||||
|
return $this->errService(__('Server Error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->ok(__('The user has been deleted'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDataUser(StoreUpdate $data): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'is_active' => $data->isActive(),
|
||||||
|
'name' => $data->getName(),
|
||||||
|
'email' => $data->getEmail(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
15
app/Services/User/BuilderCommand.php
Normal file
15
app/Services/User/BuilderCommand.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services\User;
|
||||||
|
|
||||||
|
use App\Dto\Builder\User as UserBuilderDto;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
|
|
||||||
|
final readonly class BuilderCommand
|
||||||
|
{
|
||||||
|
public function execute(Relation | Builder $query, UserBuilderDto $userBuilderDto): Relation | Builder
|
||||||
|
{
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
}
|
@ -54,4 +54,9 @@ final readonly class UserCommandHandler
|
|||||||
{
|
{
|
||||||
return Hash::make($password);
|
return Hash::make($password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleDestroy(User $user): void
|
||||||
|
{
|
||||||
|
$user->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
57
app/View/Components/Private/Forms/Checkbox.php
Normal file
57
app/View/Components/Private/Forms/Checkbox.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\View\Components\Private\Forms;
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
final class Checkbox extends Form
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly string $title,
|
||||||
|
private readonly string $name,
|
||||||
|
private readonly string $checkboxValue,
|
||||||
|
private readonly ?string $userValue = '',
|
||||||
|
private readonly ?string $notCheckedValue = null
|
||||||
|
) { }
|
||||||
|
|
||||||
|
protected function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTitle(): string
|
||||||
|
{
|
||||||
|
return Str::ucfirst($this->title);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCheckboxValue(): string
|
||||||
|
{
|
||||||
|
return (string) old($this->getRequestName(), $this->checkboxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserValue(): string
|
||||||
|
{
|
||||||
|
return (string) $this->userValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNotCheckedValue(): ?string
|
||||||
|
{
|
||||||
|
return $this->notCheckedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
return view('private.components.forms.checkbox', [
|
||||||
|
'title' => $this->getTitle(),
|
||||||
|
'name' => $this->getName(),
|
||||||
|
'requestName' => $this->getRequestName(),
|
||||||
|
'checkboxValue' => $this->getCheckboxValue(),
|
||||||
|
'userValue' => $this->getUserValue(),
|
||||||
|
'notCheckedValue' => $this->getNotCheckedValue(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
53
app/View/Components/Private/Forms/MultiCheckbox.php
Normal file
53
app/View/Components/Private/Forms/MultiCheckbox.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\View\Components\Private\Forms;
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
final class MultiCheckbox extends Form
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $title
|
||||||
|
* @param string $name
|
||||||
|
* @param array $list = [ [key => value], ... ]
|
||||||
|
* @param array $value
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly string $title,
|
||||||
|
private readonly string $name,
|
||||||
|
private readonly array $list,
|
||||||
|
private readonly array $value = []
|
||||||
|
) { }
|
||||||
|
|
||||||
|
protected function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTitle(): string
|
||||||
|
{
|
||||||
|
return Str::ucfirst($this->title);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getValue(): array
|
||||||
|
{
|
||||||
|
return old($this->getRequestName(), $this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getList(): array
|
||||||
|
{
|
||||||
|
return $this->list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
return view('private.components.forms.multi_checkbox', [
|
||||||
|
'title' => $this->getTitle(),
|
||||||
|
'name' => $this->getName(),
|
||||||
|
'requestName' => $this->getRequestName(),
|
||||||
|
'list' => $this->getList(),
|
||||||
|
'value' => $this->getValue()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -54,5 +54,10 @@
|
|||||||
"Create": "Create",
|
"Create": "Create",
|
||||||
"The group was successfully created": "The group was successfully created",
|
"The group was successfully created": "The group was successfully created",
|
||||||
"The group was successfully updated": "The group was successfully updated",
|
"The group was successfully updated": "The group was successfully updated",
|
||||||
"The group has been deleted": "The group has been deleted"
|
"The group has been deleted": "The group has been deleted",
|
||||||
|
"yes": "yes",
|
||||||
|
"no": "no",
|
||||||
|
"The user was successfully created": "The user was successfully created",
|
||||||
|
"The user was successfully updated": "The user was successfully updated",
|
||||||
|
"The user has been deleted": "The user has been deleted"
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'Role' => 'User group',
|
'Role' => 'User group',
|
||||||
|
'User' => 'Users',
|
||||||
'Allowed to watch' => 'Allowed to watch',
|
'Allowed to watch' => 'Allowed to watch',
|
||||||
'Allowed to create' => 'Allowed to create',
|
'Allowed to create' => 'Allowed to create',
|
||||||
'Allowed to edit' => 'Allowed to edit',
|
'Allowed to edit' => 'Allowed to edit',
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
return [
|
return [
|
||||||
'Dashboard' => 'Dashboard',
|
'Dashboard' => 'Dashboard',
|
||||||
'User group' => 'User group',
|
'User group' => 'User group',
|
||||||
|
'Users' => 'Users',
|
||||||
];
|
];
|
||||||
|
@ -218,5 +218,7 @@ return [
|
|||||||
'timezone' => 'timezone',
|
'timezone' => 'timezone',
|
||||||
'code' => 'code',
|
'code' => 'code',
|
||||||
'permissions' => 'permissions',
|
'permissions' => 'permissions',
|
||||||
|
'is_active' => 'is active',
|
||||||
|
'roles' => 'user group',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -54,5 +54,10 @@
|
|||||||
"Create": "Создать",
|
"Create": "Создать",
|
||||||
"The group was successfully created": "Группа успешно создана",
|
"The group was successfully created": "Группа успешно создана",
|
||||||
"The group was successfully updated": "Группа успешно обновлена",
|
"The group was successfully updated": "Группа успешно обновлена",
|
||||||
"The group has been deleted": "Группа была удалена"
|
"The group has been deleted": "Группа была удалена",
|
||||||
|
"yes": "да",
|
||||||
|
"no": "нет",
|
||||||
|
"The user was successfully created": "Пользователь был успешно создан",
|
||||||
|
"The user was successfully updated": "Пользователь был успешно обновлен",
|
||||||
|
"The user has been deleted": "Пользователь был удален"
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'Role' => 'Группа пользователей',
|
'Role' => 'Группа пользователей',
|
||||||
|
'User' => 'Пользователи',
|
||||||
'Allowed to watch' => 'Разрешено смотреть',
|
'Allowed to watch' => 'Разрешено смотреть',
|
||||||
'Allowed to create' => 'Разрешено создать',
|
'Allowed to create' => 'Разрешено создать',
|
||||||
'Allowed to edit' => 'Разрешено редактировать',
|
'Allowed to edit' => 'Разрешено редактировать',
|
||||||
|
@ -3,5 +3,6 @@
|
|||||||
return [
|
return [
|
||||||
'Dashboard' => 'Dashboard',
|
'Dashboard' => 'Dashboard',
|
||||||
'User group' => 'Группа пользователей',
|
'User group' => 'Группа пользователей',
|
||||||
|
'Users' => 'Пользователи',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -218,5 +218,7 @@ return [
|
|||||||
'timezone' => 'часовой пояс',
|
'timezone' => 'часовой пояс',
|
||||||
'code' => 'код',
|
'code' => 'код',
|
||||||
'permissions' => 'разрешения',
|
'permissions' => 'разрешения',
|
||||||
|
'is_active' => 'активен',
|
||||||
|
'roles' => 'группа пользователей',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
12
resources/views/private/components/forms/checkbox.blade.php
Normal file
12
resources/views/private/components/forms/checkbox.blade.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<div class="form-check">
|
||||||
|
@if(!is_null($notCheckedValue))
|
||||||
|
<input type="hidden" name="{{ $name }}" value="{{ $notCheckedValue }}">
|
||||||
|
@endif
|
||||||
|
<input class="form-check-input @error($requestName) is-invalid @enderror" name="{{ $name }}" type="checkbox" value="{{ $checkboxValue }}" @checked($checkboxValue === $userValue) id="form-checkbox-{{ $requestName }}">
|
||||||
|
<label class="form-check-label" for="form-checkbox-{{ $requestName }}">
|
||||||
|
{{ $title }}
|
||||||
|
</label>
|
||||||
|
@error($name)
|
||||||
|
<span class="invalid-feedback d-block">{{ $message }}</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
<div class="mb-4">
|
||||||
|
<div class="h5 pb-3">{{ $title }}</div>
|
||||||
|
@error($requestName)
|
||||||
|
<span class="invalid-feedback d-block pb-3">{{ $message }}</span>
|
||||||
|
@enderror
|
||||||
|
<div class="row">
|
||||||
|
@foreach($list as $elementValue => $elementTitle)
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="{{ $name }}" value="{{ $elementValue }}" @checked(array_search($elementValue, $value) !== false) id="form-checkbox-{{ $requestName }}-{{ $loop->index }}">
|
||||||
|
<label class="form-check-label" for="form-checkbox-{{ $requestName }}-{{ $loop->index }}">
|
||||||
|
{{ $elementTitle }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -18,6 +18,21 @@
|
|||||||
<span class="sidebar-text">{{ __('sections.Dashboard') }}</span>
|
<span class="sidebar-text">{{ __('sections.Dashboard') }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
@can('viewAny', \App\Models\User::class)
|
||||||
|
<li @class([
|
||||||
|
'nav-item',
|
||||||
|
'active' => request()->route()->named('users.*'),
|
||||||
|
])>
|
||||||
|
<a href="{{ route('users.index') }}" class="nav-link">
|
||||||
|
<span class="sidebar-icon">
|
||||||
|
<svg class="icon icon-xs me-2" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M15 14s1 0 1-1-1-4-5-4-5 3-5 4 1 1 1 1h8Zm-7.978-1A.261.261 0 0 1 7 12.996c.001-.264.167-1.03.76-1.72C8.312 10.629 9.282 10 11 10c1.717 0 2.687.63 3.24 1.276.593.69.758 1.457.76 1.72l-.008.002a.274.274 0 0 1-.014.002H7.022ZM11 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4Zm3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM6.936 9.28a5.88 5.88 0 0 0-1.23-.247A7.35 7.35 0 0 0 5 9c-4 0-5 3-5 4 0 .667.333 1 1 1h4.216A2.238 2.238 0 0 1 5 13c0-1.01.377-2.042 1.09-2.904.243-.294.526-.569.846-.816ZM4.92 10A5.493 5.493 0 0 0 4 13H1c0-.26.164-1.03.76-1.724.545-.636 1.492-1.256 3.16-1.275ZM1.5 5.5a3 3 0 1 1 6 0 3 3 0 0 1-6 0Zm3-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z"/></svg>
|
||||||
|
</span>
|
||||||
|
<span class="sidebar-text">{{ __('sections.Users') }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
|
|
||||||
@can('viewAny', \App\Models\Role::class)
|
@can('viewAny', \App\Models\Role::class)
|
||||||
<li @class([
|
<li @class([
|
||||||
'nav-item',
|
'nav-item',
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="content min-vh-100 position-relative">
|
<main class="content min-vh-100 position-relative pb-7 pb-lg-5">
|
||||||
|
|
||||||
<nav class="navbar navbar-top navbar-expand navbar-dashboard navbar-dark ps-0 pe-2 pb-2 pb-lg-3">
|
<nav class="navbar navbar-top navbar-expand navbar-dashboard navbar-dark ps-0 pe-2 pb-2 pb-lg-3">
|
||||||
<div class="container-fluid px-0">
|
<div class="container-fluid px-0">
|
||||||
|
13
resources/views/private/users/_from.blade.php
Normal file
13
resources/views/private/users/_from.blade.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@csrf
|
||||||
|
<x-private.forms.checkbox :title="__('validation.attributes.is_active')" name="is_active" checkboxValue="1" notCheckedValue="0" :userValue="(string) $user->is_active" />
|
||||||
|
<x-private.forms.input :title="__('validation.attributes.name')" name="name" type="text" :value="$user->name" required autofocus />
|
||||||
|
<x-private.forms.input :title="__('validation.attributes.email')" name="email" type="email" :value="$user->email" required />
|
||||||
|
@if (empty($user->id))
|
||||||
|
<x-private.forms.input :title="__('validation.attributes.password')" name="password" type="password" value="" required autocomplete="off" />
|
||||||
|
@endif
|
||||||
|
<hr>
|
||||||
|
<x-private.forms.multi_checkbox :title="__('validation.attributes.roles')" name="roles[]" :list="$roles" :value="$userRoles" />
|
||||||
|
<hr>
|
||||||
|
@canany(['create', 'update'], $user)
|
||||||
|
<button class="btn btn-primary" type="submit">{{ __('Save') }}</button>
|
||||||
|
@endcanany
|
8
resources/views/private/users/_top.blade.php
Normal file
8
resources/views/private/users/_top.blade.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@can('create', \App\Models\User::class)
|
||||||
|
<div class="mb-4">
|
||||||
|
<a href="{{ route('users.create') }}" class="btn btn-secondary d-inline-flex align-items-center me-2">
|
||||||
|
<svg class="icon icon-xs me-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path></svg>
|
||||||
|
{{ __('Create') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endcan
|
16
resources/views/private/users/create.blade.php
Normal file
16
resources/views/private/users/create.blade.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@section('meta_title', __('sections.Users'))
|
||||||
|
@section('h1', __('sections.Users'))
|
||||||
|
<x-private.layout>
|
||||||
|
@include('private.users._top')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card border-0 shadow components-section">
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" action="{{ route('users.store') }}">
|
||||||
|
@include('private.users._from')
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-private.layout>
|
34
resources/views/private/users/edit.blade.php
Normal file
34
resources/views/private/users/edit.blade.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
@section('meta_title', __('sections.Users'))
|
||||||
|
@section('h1', __('sections.Users'))
|
||||||
|
<x-private.layout>
|
||||||
|
@include('private.users._top')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card border-0 shadow components-section">
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" action="{{ route('users.update', $user) }}">
|
||||||
|
@method('PUT')
|
||||||
|
@include('private.users._from')
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@can('update', $user)
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card border-0 shadow components-section">
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" action="{{ route('users.update-password', $user) }}">
|
||||||
|
@method('PUT')
|
||||||
|
@csrf
|
||||||
|
<x-private.forms.input :title="__('validation.attributes.password')" name="password" type="password" value="" required autocomplete="off" />
|
||||||
|
<button class="btn btn-primary" type="submit">{{ __('Save') }}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endcan
|
||||||
|
</x-private.layout>
|
60
resources/views/private/users/index.blade.php
Normal file
60
resources/views/private/users/index.blade.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
@section('meta_title', __('sections.Users'))
|
||||||
|
@section('h1', __('sections.Users'))
|
||||||
|
<x-private.layout>
|
||||||
|
@include('private.users._top')
|
||||||
|
<div class="card border-0 shadow mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-centered table-nowrap mb-0 rounded">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th class="border-0">{{ __('validation.attributes.name') }}</th>
|
||||||
|
<th class="border-0">{{ __('validation.attributes.email') }}</th>
|
||||||
|
<th class="border-0">{{ __('validation.attributes.is_active') }}</th>
|
||||||
|
<th class="border-0 rounded-end" style="width: 150px"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($users as $user)
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('users.edit', $user) }}" class="fw-bold">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="align-text-top" viewBox="0 0 16 16">
|
||||||
|
<path d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793 14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708l-3-3zm.646 6.061L9.793 2.5 3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207l6.5-6.5zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.499.499 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11l.178-.178z"/>
|
||||||
|
</svg>
|
||||||
|
{{ $user->name }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ $user->email }}</td>
|
||||||
|
<td>
|
||||||
|
@if($user->is_active)
|
||||||
|
{{ __('yes') }}
|
||||||
|
@else
|
||||||
|
{{ __('no') }}
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@can('delete', $user)
|
||||||
|
<form method="post" action="{{ route('users.destroy', $user) }}">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="submit" class="btn btn-danger click-confirm">
|
||||||
|
{{ __('Delete') }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@endcan
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="card-footer border-0">
|
||||||
|
{{ $users->links() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@push('scripts')
|
||||||
|
@include('private._scripts._click-confirm', ['alert' => __('Do you want to delete?')])
|
||||||
|
@endpush
|
||||||
|
</x-private.layout>
|
@ -30,5 +30,7 @@ Route::middleware(['auth', 'verified', 'user.locale'])->group(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Route::resource('users', \App\Http\Controllers\Private\UsersController::class)->only(['index', 'create', 'store', 'edit', 'update', 'destroy'])->where(['user' => '[0-9]+']);
|
Route::resource('users', \App\Http\Controllers\Private\UsersController::class)->only(['index', 'create', 'store', 'edit', 'update', 'destroy'])->where(['user' => '[0-9]+']);
|
||||||
|
Route::put('users/{id}/password', [\App\Http\Controllers\Private\UsersController::class, 'updatePassword'])->name('users.update-password')->where(['id' => '[0-9]+']);
|
||||||
|
|
||||||
Route::resource('roles', \App\Http\Controllers\Private\RolesController::class)->only(['index', 'create', 'store', 'edit', 'update', 'destroy'])->where(['role' => '[0-9]+']);
|
Route::resource('roles', \App\Http\Controllers\Private\RolesController::class)->only(['index', 'create', 'store', 'edit', 'update', 'destroy'])->where(['role' => '[0-9]+']);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user