Skip to content

Commit

Permalink
feat: user management
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardotglobal committed Jul 24, 2024
1 parent 0ba2ddc commit 7254d21
Show file tree
Hide file tree
Showing 29 changed files with 635 additions and 59 deletions.
71 changes: 71 additions & 0 deletions app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Jdenticon\Identicon;
use Psr\SimpleCache\InvalidArgumentException;

class UserController
{
Expand All @@ -17,4 +26,66 @@ public function identicon(string $username): Response
->header("Cache-Control", "max-age=604800")
->header("Content-Type", "image/svg+xml");
}

/**
* @throws ValidationException
*/
public function create(Request $request)
{
$data = [
"name" => $request->name,
"username" => $request->username,
"password" => $request->password,
];

Validator::make($data, [
"name" => ["required", "string", "max:255"],

"username" => [
"required",
"string",
"max:255",
Rule::unique("users"),
],

"password" => ["required", "string"],
])
->validate();

User::create([
...$data,
"password" => Hash::make($data["password"]),
]);

return redirect("/admin/users");
}

/**
* @throws ValidationException
*/
public function delete(Request $request): void
{
Validator::validate(["username" => $request->username], ["username" => "required|string|max:255"]);
$user = User::whereUsername($request->username);

if ($user->exists()) abort(400, message: "User does not exist");

Cache::put("delete_confirm_$user->id", true, now()->addMinutes(3));
}

/**
* @throws InvalidArgumentException
* @throws ValidationException
*/
public function delete_confirm(Request $request): void
{
Validator::validate(["username" => $request->username], ["username" => "required|string|max:255"]);
$user = User::whereUsername($request->username);

if ($user->exists()) abort(400, message: "User does not exist");
if (Cache::get("delete_confirm_$user->id", false) === false) abort(400, message: "Delete request timeouted or doesn't exist");

Cache::delete("delete_confirm_$user->id");
$user->delete();
}
}
24 changes: 24 additions & 0 deletions app/Http/Middleware/IsAdmin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class IsAdmin
{
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->user()->role !== "admin") {
return redirect("/");
}

return $next($request);
}
}
28 changes: 28 additions & 0 deletions app/Livewire/DeleteUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Livewire;

use App\Models\User;
use Closure;
use Illuminate\View\View;
use LivewireUI\Modal\ModalComponent;

class DeleteUser extends ModalComponent
{
public User $user;

public function render(): View|Closure|string
{
return view("livewire.delete-user");
}

public function delete(): void
{
if (!$this->user->exists()) abort(400, message: "User does not exist");

$this->user->delete();
$this->closeModal();

$this->js("window.location.reload()");
}
}
32 changes: 32 additions & 0 deletions app/Livewire/EditUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Livewire;

use App\Models\User;
use Closure;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;
use LivewireUI\Modal\ModalComponent;
use Throwable;

class EditUser extends ModalComponent
{
public User $user;
public string $newPassword = "";

public function render(): View|Closure|string
{
return view("livewire.edit-user");
}

/**
* @throws Throwable
*/
public function save(): void
{
$this->user->password = Hash::make($this->newPassword);

$this->user->saveOrFail();
$this->closeModal();
}
}
3 changes: 2 additions & 1 deletion app/Models/BookTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
*
*
*
* @property string $name the name of the tag
* @property int $book the id of the book this tag belongs to
Expand All @@ -18,6 +18,7 @@
* @method static \Illuminate\Database\Eloquent\Builder|BookTag whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|BookTag whereLink($value)
* @method static \Illuminate\Database\Eloquent\Builder|BookTag whereName($value)
* @property string $link
* @mixin \Eloquent
*/
class BookTag extends Model
Expand Down
3 changes: 2 additions & 1 deletion app/Models/Series.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

/**
*
*
*
* @property string $name the name of the series
* @property string $sort the name of the series in a sortable format
Expand All @@ -22,6 +22,7 @@
* @method static \Illuminate\Database\Eloquent\Builder|Series whereLink($value)
* @method static \Illuminate\Database\Eloquent\Builder|Series whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|Series whereSort($value)
* @property-read Collection<int, \App\Models\Book> $books
* @mixin \Eloquent
*/
class Series extends Model
Expand Down
11 changes: 10 additions & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Illuminate\Foundation\Auth\User as Authenticatable;
/**
*
*
*
* @property int $id
* @property string $name
Expand All @@ -23,6 +23,8 @@
* @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUsername($value)
* @property string $role
* @method static \Illuminate\Database\Eloquent\Builder|User whereRole($value)
* @mixin \Eloquent
*/
class User extends Authenticatable
Expand All @@ -33,4 +35,11 @@ class User extends Authenticatable
* @var string
*/
protected $table = "users";

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ["name", "username", "password"];
}
7 changes: 6 additions & 1 deletion app/View/Components/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\View\Components;

use App\Models\User;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
Expand All @@ -13,8 +14,12 @@ class Header extends Component
*/
public function render(): View|Closure|string
{
/** @var User $user */
$user = request()->user();

return view("components.header", [
"username" => request()->user()->username,
"username" => $user->username,
"is_admin" => $user->role === "admin"
]);
}
}
30 changes: 30 additions & 0 deletions app/View/Pages/UsersPage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\View\Pages;

use App\Http\Resources\BookResource;
use App\Interfaces\PageComponent;
use App\Models\Book;
use App\Models\User;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;

class UsersPage extends PageComponent
{
/**
* Get the view / contents that represent the component.
*/
protected function _render(Request $request): View|Closure|string
{
return view("admin.users", [
"users" => User::all()
->map(fn($user) => [
"id" => $user->id,
"name" => $user->name,
"username" => $user->username,
])
->toArray()
]);
}
}
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"jdenticon/jdenticon": "^1.0",
"laravel/fortify": "^1.21",
"laravel/framework": "^11.9",
"laravel/tinker": "^2.9"
"laravel/tinker": "^2.9",
"livewire/livewire": "^3.5",
"wire-elements/modal": "^2.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^3.1",
Expand Down
Loading

0 comments on commit 7254d21

Please sign in to comment.