acct_type, UserActions::ListAllUsersAsParentforUserCreation)) { return ResponseHelper::returnUnauthorized(); } $query = User::orderByDesc('id'); if ($search = $request->input('search')) { $query->where(function ($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('mobile_number', 'like', "%{$search}%") ->orWhere('username', 'like', "%{$search}%"); }); } if ($acctType = $request->input('acct_type')) $query->where('acct_type', $acctType); if ($request->input('active_only')) $query->where('active', true); $users = $query->paginate((int) $request->input('per_page', 25)); return response()->json(['success' => true, 'data' => $users]); } public function show(Request $request) { $target = $request->input('target'); $user = is_numeric($target) ? User::find($target) : User::where('hashkey', $target)->first(); if (!$user) return ResponseHelper::returnError('User not found', 404); if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ViewUserInfo)) { return ResponseHelper::returnUnauthorized(); } return response()->json(['success' => true, 'data' => $this->present($user)]); } public function store(Request $request) { if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::CreateUser)) { return ResponseHelper::returnUnauthorized(); } $validator = Validator::make($request->all(), [ 'name' => 'required|string|max:255', 'mobile_number' => 'required|string|max:20|unique:users,mobile_number', 'username' => 'nullable|string|max:100|unique:users,username', 'password' => 'required|string|min:6', 'acct_type' => 'required|string', 'parentuid' => 'nullable|integer|exists:users,id', ]); if ($validator->fails()) { return response()->json(['success' => false, 'errors' => $validator->errors()], 422); } $acctType = UserTypes::tryFrom($request->input('acct_type')); if (!$acctType) { return ResponseHelper::returnError('Invalid account type', 422); } $user = User::create([ 'name' => $request->input('name'), 'mobile_number' => $request->input('mobile_number'), 'username' => $request->input('username'), 'password' => Hash::make($request->input('password')), 'acct_type' => $acctType, 'parentuid' => $request->input('parentuid', Auth::id()), 'hashkey' => hash('sha256', uniqid((string) now(), true)), 'active' => true, ]); return response()->json(['success' => true, 'data' => $this->present($user), 'message' => 'User created']); } public function update(Request $request) { $target = $request->input('target'); $user = User::where('hashkey', $target)->first(); if (!$user) return ResponseHelper::returnError('User not found', 404); if (!UserPermissions::isActionPermitted($target, UserActions::ModifyUser)) { return ResponseHelper::returnUnauthorized(); } $allowedFields = ['name', 'username', 'acct_type', 'nickname', 'fullname']; $data = $request->only($allowedFields); if (isset($data['acct_type'])) { $acctType = UserTypes::tryFrom($data['acct_type']); if (!$acctType) return ResponseHelper::returnError('Invalid account type', 422); $data['acct_type'] = $acctType; } $user->update($data); return response()->json(['success' => true, 'data' => $this->present($user), 'message' => 'User updated']); } public function setActive(Request $request) { $target = $request->input('target'); $user = User::where('hashkey', $target)->first(); if (!$user) return ResponseHelper::returnError('User not found', 404); $active = (bool) $request->input('active', true); $action = $active ? UserActions::SetActiveUser : UserActions::SetInActiveUser; if (!UserPermissions::isActionPermitted($target, $action)) { return ResponseHelper::returnUnauthorized(); } $user->update(['active' => $active]); return response()->json(['success' => true, 'data' => $this->present($user)]); } public function changePassword(Request $request) { $target = $request->input('target'); $user = User::where('hashkey', $target)->first(); if (!$user) return ResponseHelper::returnError('User not found', 404); if (!UserPermissions::isActionPermitted($target, UserActions::ChangeUserPassword)) { return ResponseHelper::returnUnauthorized(); } $validator = Validator::make($request->all(), [ 'password' => 'required|string|min:6', ]); if ($validator->fails()) { return response()->json(['success' => false, 'errors' => $validator->errors()], 422); } $user->update(['password' => Hash::make($request->input('password'))]); // Force logout all sessions for this user Redis::del("user_session:{$user->id}"); return response()->json(['success' => true, 'message' => 'Password changed']); } public function forceLogout(Request $request) { $target = $request->input('target'); $user = User::where('hashkey', $target)->first(); if (!$user) return ResponseHelper::returnError('User not found', 404); if (!UserPermissions::isActionPermitted($target, UserActions::ForceLogoutUser)) { return ResponseHelper::returnUnauthorized(); } Redis::del("user_session:{$user->id}"); return response()->json(['success' => true, 'message' => 'User session cleared']); } public function accountTypes() { $types = collect(UserTypes::cases())->map(fn ($t) => [ 'value' => $t->value, 'label' => ucwords(str_replace('_', ' ', $t->value)), ]); return response()->json(['success' => true, 'data' => $types]); } private function present(User $user): array { return [ 'id' => $user->id, 'hashkey' => $user->hashkey, 'name' => $user->name, 'fullname' => $user->fullname, 'nickname' => $user->nickname, 'username' => $user->username, 'mobile_number' => $user->mobile_number, 'acct_type' => $user->acct_type, 'active' => (bool) $user->active, 'parentuid' => $user->parentuid, 'created_at' => $user->created_at, 'updated_at' => $user->updated_at, ]; } }