mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-28 17:02:04 +03:00
Added user-update API endpoint
- Required changing the docs generator to handle more complex object-style rules. Bit of a hack for some types (password). - Extracted core update logic to repo for sharing with API. - Moved user update language string to align with activity/logging system. - Added tests to cover.
This commit is contained in:
@ -10,7 +10,6 @@ use Illuminate\Http\JsonResponse;
|
||||
abstract class ApiController extends Controller
|
||||
{
|
||||
protected $rules = [];
|
||||
protected $fieldsToExpose = [];
|
||||
|
||||
/**
|
||||
* Provide a paginated listing JSON response in a standard format
|
||||
@ -31,7 +30,7 @@ abstract class ApiController extends Controller
|
||||
* Get the validation rules for this controller.
|
||||
* Defaults to a $rules property but can be a rules() method.
|
||||
*/
|
||||
public function getValdationRules(): array
|
||||
public function getValidationRules(): array
|
||||
{
|
||||
if (method_exists($this, 'rules')) {
|
||||
return $this->rules();
|
||||
|
@ -6,6 +6,8 @@ use BookStack\Auth\User;
|
||||
use BookStack\Auth\UserRepo;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
use Illuminate\Validation\Rules\Unique;
|
||||
|
||||
class UserApiController extends ApiController
|
||||
{
|
||||
@ -15,21 +17,35 @@ class UserApiController extends ApiController
|
||||
'email', 'created_at', 'updated_at', 'last_activity_at', 'external_auth_id'
|
||||
];
|
||||
|
||||
protected $rules = [
|
||||
'create' => [
|
||||
],
|
||||
'update' => [
|
||||
],
|
||||
'delete' => [
|
||||
'migrate_ownership_id' => ['integer', 'exists:users,id'],
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct(UserRepo $userRepo)
|
||||
{
|
||||
$this->userRepo = $userRepo;
|
||||
}
|
||||
|
||||
protected function rules(int $userId = null): array
|
||||
{
|
||||
return [
|
||||
'create' => [
|
||||
],
|
||||
'update' => [
|
||||
'name' => ['min:2'],
|
||||
'email' => [
|
||||
'min:2',
|
||||
'email',
|
||||
(new Unique('users', 'email'))->ignore($userId ?? null)
|
||||
],
|
||||
'external_auth_id' => ['string'],
|
||||
'language' => ['string'],
|
||||
'password' => [Password::default()],
|
||||
'roles' => ['array'],
|
||||
'roles.*' => ['integer'],
|
||||
],
|
||||
'delete' => [
|
||||
'migrate_ownership_id' => ['integer', 'exists:users,id'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a listing of users in the system.
|
||||
* Requires permission to manage users.
|
||||
@ -54,10 +70,26 @@ class UserApiController extends ApiController
|
||||
{
|
||||
$this->checkPermission('users-manage');
|
||||
|
||||
$singleUser = $this->userRepo->getById($id);
|
||||
$this->singleFormatter($singleUser);
|
||||
$user = $this->userRepo->getById($id);
|
||||
$this->singleFormatter($user);
|
||||
|
||||
return response()->json($singleUser);
|
||||
return response()->json($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing user in the system.
|
||||
* @throws \BookStack\Exceptions\UserUpdateException
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
$this->checkPermission('users-manage');
|
||||
|
||||
$data = $this->validate($request, $this->rules($id)['update']);
|
||||
$user = $this->userRepo->getById($id);
|
||||
$this->userRepo->update($user, $data, userCan('users-manage'));
|
||||
$this->singleFormatter($user);
|
||||
|
||||
return response()->json($user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,51 +168,19 @@ class UserController extends Controller
|
||||
$this->preventAccessInDemoMode();
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $id);
|
||||
|
||||
$this->validate($request, [
|
||||
$validated = $this->validate($request, [
|
||||
'name' => ['min:2'],
|
||||
'email' => ['min:2', 'email', 'unique:users,email,' . $id],
|
||||
'password' => ['required_with:password_confirm', Password::default()],
|
||||
'password-confirm' => ['same:password', 'required_with:password'],
|
||||
'setting' => ['array'],
|
||||
'language' => ['string'],
|
||||
'roles' => ['array'],
|
||||
'roles.*' => ['integer'],
|
||||
'profile_image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
||||
]);
|
||||
|
||||
$user = $this->userRepo->getById($id);
|
||||
$user->fill($request->except(['email']));
|
||||
|
||||
// Email updates
|
||||
if (userCan('users-manage') && $request->filled('email')) {
|
||||
$user->email = $request->get('email');
|
||||
}
|
||||
|
||||
// Refresh the slug if the user's name has changed
|
||||
if ($user->isDirty('name')) {
|
||||
$user->refreshSlug();
|
||||
}
|
||||
|
||||
// Role updates
|
||||
if (userCan('users-manage') && $request->filled('roles')) {
|
||||
$roles = $request->get('roles');
|
||||
$this->userRepo->setUserRoles($user, $roles);
|
||||
}
|
||||
|
||||
// Password updates
|
||||
if ($request->filled('password')) {
|
||||
$password = $request->get('password');
|
||||
$user->password = bcrypt($password);
|
||||
}
|
||||
|
||||
// External auth id updates
|
||||
if (user()->can('users-manage') && $request->filled('external_auth_id')) {
|
||||
$user->external_auth_id = $request->get('external_auth_id');
|
||||
}
|
||||
|
||||
// Save user-specific settings
|
||||
if ($request->filled('setting')) {
|
||||
foreach ($request->get('setting') as $key => $value) {
|
||||
setting()->putUser($user, $key, $value);
|
||||
}
|
||||
}
|
||||
$this->userRepo->update($user, $validated, userCan('users-manage'));
|
||||
|
||||
// Save profile image if in request
|
||||
if ($request->hasFile('profile_image')) {
|
||||
@ -220,6 +188,7 @@ class UserController extends Controller
|
||||
$this->imageRepo->destroyImage($user->avatar);
|
||||
$image = $this->imageRepo->saveNew($imageUpload, 'user', $user->id);
|
||||
$user->image_id = $image->id;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
// Delete the profile image if reset option is in request
|
||||
@ -227,11 +196,7 @@ class UserController extends Controller
|
||||
$this->imageRepo->destroyImage($user->avatar);
|
||||
}
|
||||
|
||||
$user->save();
|
||||
$this->showSuccessNotification(trans('settings.users_edit_success'));
|
||||
$this->logActivity(ActivityType::USER_UPDATE, $user);
|
||||
|
||||
$redirectUrl = userCan('users-manage') ? '/settings/users' : ('/settings/users/' . $user->id);
|
||||
$redirectUrl = userCan('users-manage') ? '/settings/users' : "/settings/users/{$user->id}";
|
||||
|
||||
return redirect($redirectUrl);
|
||||
}
|
||||
|
Reference in New Issue
Block a user