Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions app/Http/Controllers/Admin/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,13 @@ public function edit(User $user)
return Inertia::render('admin/users/CreateOrEdit', [
'user' => $user->load(['roles', 'permissions']),
'permissions' => Permission::select('name')->get(),
'shouldHideOptions' => (Auth::id() === $user->id && !Auth::user()->can('manage users')), //hide options when showing own profile && don't have manage user permission.
]);
}

public function update(UpdateUserRequest $request, User $user)
{
if (
($request->user()->id !== $user->id &&
!$request->user()->can('manage users')) || $user->email === "check@example.com"
) {
throw UnauthorizedException::forPermissions(['manage users']);
if ($user->email === 'check@example.com') {
abort(403, 'This demo user cannot be modified.');
}

$validated = $request->validated();
Expand Down
39 changes: 39 additions & 0 deletions app/Http/Controllers/ProfileController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Http\Controllers;

use App\Http\Requests\Profile\UpdateProfileRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;

class ProfileController extends Controller
{
public function edit(Request $request)
{
return Inertia::render('Profile', [
'user' => $request->user(),
]);
}

public function update(UpdateProfileRequest $request)
{
$user = $request->user();
$validated = $request->validated();

if ($request->hasFile('file')) {
$path = $request->file('file')->store('users/profile-images');

if ($user->image_path) {
Storage::delete($user->image_path);
}

$validated['image_path'] = $path;
}

$user->update($validated);

return redirect()->route('profile.edit')
->with('success', 'Profile updated successfully.');
}
}
1 change: 1 addition & 0 deletions app/Http/Middleware/HandleInertiaRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function share(Request $request): array
'name' => config('app.name'),
'auth' => [
'user' => $request->user(),
'can_access_admin' => $request->user()?->can('view admin') ?? false,
],
'flash' => [
'success' => fn() => $request->session()->get('success'),
Expand Down
46 changes: 46 additions & 0 deletions app/Http/Requests/Profile/UpdateProfileRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace App\Http\Requests\Profile;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;

class UpdateProfileRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return $this->user() !== null;
}

protected function prepareForValidation(): void
{
if (! $this->filled('password')) {
$this->replace($this->except('password'));
}
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$userId = $this->user()->id;

return [
'name' => ['required', 'string', 'max:255'],
'password' => ['sometimes', 'nullable', 'string', 'min:6'],
'file' => ['sometimes', 'nullable', 'image', 'max:2048'],
'about' => ['sometimes', 'nullable', 'string'],
'title' => ['sometimes', 'nullable', 'string', 'max:255'],
'institution' => ['sometimes', 'nullable', 'string', 'max:255'],
'facebook' => ['sometimes', 'nullable', 'string', 'max:255'],
'instagram' => ['sometimes', 'nullable', 'string', 'max:255'],
'github' => ['sometimes', 'nullable', 'string', 'max:255'],
];
}
}
9 changes: 3 additions & 6 deletions app/Http/Requests/User/UpdateUserRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,11 @@ public function rules(): array
'facebook' => ['sometimes', 'nullable', 'string', 'max:255'],
'instagram' => ['sometimes', 'nullable', 'string', 'max:255'],
'github' => ['sometimes', 'nullable', 'string', 'max:255'],
'role' => ['sometimes', 'string'],
'permissions' => ['sometimes', 'array'],
'permissions.*' => ['string', 'exists:permissions,name'],
];

if ($this->user()->can('manage users')) {
$rules['role'] = ['sometimes', 'string'];
$rules['permissions'] = ['sometimes', 'array'];
$rules['permissions.*'] = ['string', 'exists:permissions,name'];
}

return $rules;
}
}
12 changes: 12 additions & 0 deletions resources/js/components/NavBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Moon,
Sun,
Monitor,
User,
} from 'lucide-vue-next';
import { computed, ref, onMounted, onBeforeUnmount } from 'vue';
import { useDarkMode } from '@/lib/useDarkMode';
Expand All @@ -23,6 +24,7 @@ defineProps({
const { theme, toggle } = useDarkMode();

const user = computed(() => usePage().props.auth?.user);
const canAccessAdmin = computed(() => usePage().props.auth?.can_access_admin);

const dropdownOpen = ref(false);
const dropdownRef = ref<HTMLElement | null>(null);
Expand Down Expand Up @@ -149,6 +151,16 @@ onBeforeUnmount(() => {
</div>

<Link
href="/profile"
class="flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium text-slate-600 transition-colors hover:bg-slate-50 hover:text-slate-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100"
@click="closeDropdown"
>
<User class="h-4 w-4 text-slate-400" />
Profile
</Link>

<Link
v-if="canAccessAdmin"
:href="isAdmin ? '/' : '/admin'"
class="flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium text-slate-600 transition-colors hover:bg-slate-50 hover:text-slate-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100"
@click="closeDropdown"
Expand Down
12 changes: 1 addition & 11 deletions resources/js/layouts/AdminLayout.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
<script setup lang="ts">
import { usePage } from '@inertiajs/vue3';
import {
LayoutDashboard,
Users,
BookOpen,
Bell,
Book,
User,
} from 'lucide-vue-next';
import { LayoutDashboard, Users, BookOpen, Bell, Book } from 'lucide-vue-next';
import { ref } from 'vue';
import DesktopSidebar from '@/components/admin/DesktopSidebar.vue';
import MobileSideBar from '@/components/admin/MobileSideBar.vue';
Expand All @@ -16,14 +8,12 @@ import NavBar from '@/components/NavBar.vue';
import ToastNotification from '@/components/ToastNotification.vue';

const isMobileSidebarOpen = ref(false);
const myId = usePage().props.auth.user.id;
const navigation = [
{ name: 'Dashboard', to: '/admin', icon: LayoutDashboard },
{ name: 'Manage Contents', to: '/admin/subjects', icon: BookOpen },
{ name: 'Manage Blogs', to: '/admin/blogs', icon: Book },
{ name: 'Site Notice', to: '/admin/notice', icon: Bell },
{ name: 'Users', to: '/admin/users', icon: Users },
{ name: 'My Profile', to: `/admin/users/edit/${myId}`, icon: User },
];

const openMobileSidebar = () => {
Expand Down
Loading