Skip to content

Commit 9cdc18f

Browse files
authored
Merge pull request #43 from savannabits/1.0-dev
User Role Assignment Update
2 parents 0f7d030 + bcfbf95 commit 9cdc18f

File tree

6 files changed

+119
-16
lines changed

6 files changed

+119
-16
lines changed

publishes/acacia/Users/Http/Controllers/Api/UserController.php

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010
use Acacia\Users\Http\Requests\User\StoreRequest;
1111
use Acacia\Users\Http\Requests\User\UpdateRequest;
1212
use Acacia\Users\Http\Requests\User\DestroyRequest;
13+
use Illuminate\Auth\Access\AuthorizationException;
1314
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
1415
use Illuminate\Http\JsonResponse;
1516
use Illuminate\Http\Request;
1617
use Illuminate\Routing\Controller;
18+
use Log;
1719
use Savannabits\Acacia\Helpers\ApiResponse;
1820
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
1921
use Illuminate\Foundation\Validation\ValidatesRequests;
22+
use Throwable;
2023

2124
class UserController extends Controller
2225
{
@@ -38,8 +41,8 @@ public function index(IndexRequest $request): JsonResponse
3841
->message("List of Users")
3942
->payload($data)
4043
->send();
41-
} catch (\Throwable $e) {
42-
\Log::error($e);
44+
} catch (Throwable $e) {
45+
Log::error($e);
4346
return $this->api
4447
->failed()
4548
->code(500)
@@ -56,8 +59,8 @@ public function dt(DtRequest $request): LengthAwarePaginator|JsonResponse
5659
{
5760
try {
5861
return $this->repo->dt();
59-
} catch (\Throwable $e) {
60-
\Log::error($e);
62+
} catch (Throwable $e) {
63+
Log::error($e);
6164
return $this->api
6265
->failed()
6366
->code(500)
@@ -81,8 +84,8 @@ public function store(StoreRequest $request): JsonResponse
8184
->message($success)
8285
->payload($payload)
8386
->send();
84-
} catch (\Throwable $e) {
85-
\Log::error($e);
87+
} catch (Throwable $e) {
88+
Log::error($e);
8689
return $this->api
8790
->failed()
8891
->code(500)
@@ -107,8 +110,8 @@ public function show(ViewRequest $request, User $user): JsonResponse
107110
->message($success)
108111
->payload($payload)
109112
->send();
110-
} catch (\Throwable $e) {
111-
\Log::error($e);
113+
} catch (Throwable $e) {
114+
Log::error($e);
112115
return $this->api
113116
->failed()
114117
->code(500)
@@ -135,8 +138,8 @@ public function update(UpdateRequest $request, User $user): JsonResponse
135138
->message($success)
136139
->payload($payload)
137140
->send();
138-
} catch (\Throwable $e) {
139-
\Log::error($e);
141+
} catch (Throwable $e) {
142+
Log::error($e);
140143
return $this->api
141144
->failed()
142145
->code(500)
@@ -161,8 +164,37 @@ public function destroy(DestroyRequest $request, User $user): JsonResponse
161164
->message($success)
162165
->payload($payload)
163166
->send();
164-
} catch (\Throwable $e) {
165-
\Log::error($e);
167+
} catch (Throwable $e) {
168+
Log::error($e);
169+
return $this->api
170+
->failed()
171+
->code(500)
172+
->message($e->getMessage())
173+
->send();
174+
}
175+
}
176+
177+
/**
178+
* @throws AuthorizationException
179+
*/
180+
public function toggleRole(Request $request, User $user): JsonResponse
181+
{
182+
$this->authorize('update',$user);
183+
$validated = $request->validate([
184+
'role_id' => ['required','integer'],
185+
'assigned' => ['required','boolean'],
186+
]);
187+
try {
188+
$payload = $this->repo
189+
->setModel($user)
190+
->toggleRole((object) $validated);
191+
$success = "Record updated successfully";
192+
return $this->api
193+
->success()
194+
->message($success)
195+
->send();
196+
} catch (Throwable $e) {
197+
Log::error($e);
166198
return $this->api
167199
->failed()
168200
->code(500)

publishes/acacia/Users/Js/Pages/Partials/EditForm.vue

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@
7070
</div>
7171
</form>
7272
</TabPanel>
73-
<TabPanel header="Assign Roles"> Assign Roles </TabPanel>
73+
<TabPanel header="Assign Roles">
74+
<template v-for="role in model.assigned_roles">
75+
<div class="field-checkbox flex items-center gap-2 gap-x-4">
76+
<Checkbox @update:modelValue="toggleRole($event,role)" :id="role.id" v-model="role.assigned" :binary="true" />
77+
<label :for="role.id">{{role.name}}</label>
78+
</div>
79+
<Divider/>
80+
</template>
81+
</TabPanel>
7482
</TabView>
7583
<Message v-else severity="error"
7684
>You are not authorized to perform this action</Message
@@ -98,14 +106,33 @@ import TabPanel from "primevue/tabpanel";
98106
import InputText from "primevue/inputtext";
99107
import AcaciaDatepicker from "@/Components/AcaciaDatepicker.vue";
100108
import Password from "primevue/password";
109+
import Checkbox from "primevue/checkbox";
110+
import Divider from "primevue/divider";
101111
const emit = defineEmits(["updated", "error"]);
102-
const props = defineProps({ model: {} });
112+
const props = defineProps({ model: Object });
103113
const flash = computed(() => usePage().props?.value?.flash) as any;
104114
const existingTables = ref([]);
105115
const showModal = ref(false);
106116
const toast = useToast();
107117
const model = props.model;
108118
const form = useForm({ ...model });
119+
const toggleRole = async (value,role) => {
120+
axios.post(route('api.v1.users.user.toggle-role',model),{role_id: role.id, assigned: value}).then(res => {
121+
toast.add({
122+
severity: "success",
123+
summary: `Role ${value ? 'Assigned': 'Revoked'}`,
124+
detail: `The role assignment has been successfully updated.`,
125+
life: 1000,
126+
});
127+
}).catch(err => {
128+
toast.add({
129+
severity: "error",
130+
summary: "Error",
131+
detail: err?.response?.data?.message || err?.message || err,
132+
life: 2000,
133+
});
134+
})
135+
}
109136
const updateModel = async () => {
110137
form.put(route("acacia.auth.users.update", model), {
111138
onSuccess: (res) => {

publishes/acacia/Users/Js/Pages/Partials/ShowForm.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,15 @@
5454
</AcaciaDd>
5555
</dl>
5656
</TabPanel>
57-
<TabPanel header="Roles"> Assigned Roles </TabPanel>
57+
<TabPanel lazy header="Roles">
58+
<template v-for="role in model.assigned_roles">
59+
<div class="field-checkbox flex items-center gap-2 gap-x-4">
60+
<Checkbox :id="role.id" :disabled="true" v-model="role.assigned" :binary="true" />
61+
<label :for="role.id">{{role.name}}</label>
62+
</div>
63+
<Divider/>
64+
</template>
65+
</TabPanel>
5866
</TabView>
5967
<Message v-else severity="error"
6068
>You are not authorized to view this record</Message
@@ -78,6 +86,8 @@ import AcaciaDd from "@/Components/AcaciaDd.vue";
7886
import TabView from "primevue/tabview";
7987
import TabPanel from "primevue/tabpanel";
8088
import InputText from "primevue/inputtext";
89+
import Checkbox from "primevue/checkbox";
90+
import Divider from "primevue/divider";
8191
import AcaciaDatepicker from "@/Components/AcaciaDatepicker.vue";
8292
import Password from "primevue/password";
8393
const emit = defineEmits(["updated", "error"]);

publishes/acacia/Users/Models/User.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Acacia\Users\Models;
44

5+
use Acacia\Roles\Models\Role;
56
use Illuminate\Database\Eloquent\Factories\HasFactory;
67
use Acacia\Users\Database\Factories\UserFactory;
8+
use Illuminate\Support\Collection;
79
use Laravel\Scout\Searchable;
810

911
class User extends \App\Models\User
@@ -48,6 +50,16 @@ protected function getCanAttribute(): array
4850
->toArray();
4951
}
5052

53+
public function getAssignedRolesAttribute(): \Illuminate\Database\Eloquent\Collection|Collection
54+
{
55+
$authUser = \App\Models\User::query()->find($this->id);
56+
$roles = Role::all();
57+
return $roles->map(function (Role $role) use (&$authUser) {
58+
$role->assigned = $authUser->hasRole($role?->name);
59+
return $role;
60+
});
61+
}
62+
5163
protected static function newFactory(): UserFactory
5264
{
5365
return UserFactory::new();

publishes/acacia/Users/Repositories/Users.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
namespace Acacia\Users\Repositories;
44

5+
use Acacia\Roles\Models\Role;
6+
use Hash;
57
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
8+
use Illuminate\Support\Collection;
9+
use PrimevueDatatables;
610
use Throwable;
711
use Illuminate\Support\Str;
812
use Acacia\Users\Models\User;
@@ -43,6 +47,9 @@ public function store(object $data): ?User
4347
{
4448
$relationships = $this->relationships;
4549
$model = new User((array) $data);
50+
if (isset($data->password) && $data->password) {
51+
$model->password = Hash::make($data->password);
52+
}
4653
foreach ($relationships as $relationship) {
4754
$method = Str::snake($relationship);
4855
if (isset($data->$method) && $data->$method?->id) {
@@ -57,6 +64,7 @@ public function show(): User
5764
{
5865
$relationships = $this->relationships;
5966
$this->model->load($relationships);
67+
$this->model->append('assigned_roles');
6068
return $this->model;
6169
}
6270

@@ -72,6 +80,9 @@ public function update(object $data): User
7280
}
7381
}
7482
$this->model->update((array) $data);
83+
if (isset($data->password) && $data->password) {
84+
$this->model->password = Hash::make($data->password);
85+
}
7586

7687
$this->model->saveOrFail();
7788
return $this->model;
@@ -81,9 +92,19 @@ public function destroy(): bool
8192
{
8293
return !!$this->model->delete();
8394
}
95+
public function toggleRole(object $data): bool
96+
{
97+
$authUser = \App\Models\User::query()->find($this->model->id);
98+
if ($data->assigned) {
99+
$authUser->assignRole($data->role_id);
100+
} else {
101+
$authUser->removeRole($data->role_id);
102+
}
103+
return true;
104+
}
84105
public function dt(): LengthAwarePaginator
85106
{
86107
$q = User::query();
87-
return \PrimevueDatatables::of($q)->make();
108+
return PrimevueDatatables::of($q)->make();
88109
}
89110
}

publishes/acacia/Users/Routes/api.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
->middleware(["auth:sanctum"])
1818
->as("api.v1.")
1919
->group(function () {
20+
Route::match(['put','post'],'users/{user}/role',[\Acacia\Users\Http\Controllers\Api\UserController::class,'toggleRole'])->name('users.user.toggle-role');
2021
Route::get("users/dt", "Api\UserController@dt")->name("users.dt");
2122
Route::apiResource("users", "Api\UserController");
2223
});

0 commit comments

Comments
 (0)