Changeset View
Changeset View
Standalone View
Standalone View
src/app/Http/Controllers/API/UsersController.php
<?php | <?php | ||||
namespace App\Http\Controllers\API; | namespace App\Http\Controllers\API; | ||||
use App\Http\Controllers\Controller; | use App\Http\Controllers\Controller; | ||||
use App\Domain; | use App\Domain; | ||||
use App\Rules\UserEmailDomain; | use App\Rules\UserEmailDomain; | ||||
use App\Rules\UserEmailLocal; | use App\Rules\UserEmailLocal; | ||||
use App\Sku; | |||||
use App\User; | use App\User; | ||||
use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||
use Illuminate\Support\Facades\Auth; | use Illuminate\Support\Facades\Auth; | ||||
use Illuminate\Support\Facades\DB; | use Illuminate\Support\Facades\DB; | ||||
use Illuminate\Support\Facades\Validator; | use Illuminate\Support\Facades\Validator; | ||||
use Illuminate\Support\Str; | use Illuminate\Support\Str; | ||||
class UsersController extends Controller | class UsersController extends Controller | ||||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | protected function respondWithToken($token) | ||||
); | ); | ||||
} | } | ||||
/** | /** | ||||
* Display information on the user account specified by $id. | * Display information on the user account specified by $id. | ||||
* | * | ||||
* @param int $id The account to show information for. | * @param int $id The account to show information for. | ||||
* | * | ||||
* @return \Illuminate\Http\JsonResponse|void | * @return \Illuminate\Http\JsonResponse | ||||
*/ | */ | ||||
public function show($id) | public function show($id) | ||||
{ | { | ||||
$user = User::find($id); | $user = User::find($id); | ||||
if (empty($user)) { | if (empty($user)) { | ||||
return $this->errorResponse(404); | return $this->errorResponse(404); | ||||
} | } | ||||
if (!$this->guard()->user()->canRead($user)) { | if (!$this->guard()->user()->canRead($user)) { | ||||
return $this->errorResponse(403); | return $this->errorResponse(403); | ||||
} | } | ||||
$response = $this->userResponse($user); | $response = $this->userResponse($user); | ||||
// Simplified Entitlement/SKU information, | |||||
// TODO: I agree this format may need to be extended in future | |||||
$response['skus'] = []; | |||||
foreach ($user->entitlements as $ent) { | |||||
$sku = $ent->sku; | |||||
$response['skus'][$sku->id] = [ | |||||
// 'cost' => $ent->cost, | |||||
'count' => isset($response['skus'][$sku->id]) ? $response['skus'][$sku->id]['count'] + 1 : 1, | |||||
]; | |||||
} | |||||
return response()->json($response); | return response()->json($response); | ||||
} | } | ||||
/** | /** | ||||
* User status (extended) information | * User status (extended) information | ||||
* | * | ||||
* @param \App\User $user User object | * @param \App\User $user User object | ||||
* | * | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | // 'cost' => $ent->cost, | ||||
* | * | ||||
* @param \Illuminate\Http\Request $request The API request. | * @param \Illuminate\Http\Request $request The API request. | ||||
* | * | ||||
* @return \Illuminate\Http\JsonResponse The response | * @return \Illuminate\Http\JsonResponse The response | ||||
*/ | */ | ||||
public function store(Request $request) | public function store(Request $request) | ||||
{ | { | ||||
$current_user = $this->guard()->user(); | $current_user = $this->guard()->user(); | ||||
$owner = $current_user->wallet()->owner; | |||||
if ($current_user->wallet()->owner->id != $current_user->id) { | if ($owner->id != $current_user->id) { | ||||
return $this->errorResponse(403); | return $this->errorResponse(403); | ||||
} | } | ||||
if ($error_response = $this->validateUserRequest($request, null, $settings)) { | if ($error_response = $this->validateUserRequest($request, null, $settings)) { | ||||
return $error_response; | return $error_response; | ||||
} | } | ||||
if (empty($request->package) || !($package = \App\Package::find($request->package))) { | |||||
$errors = ['package' => \trans('validation.packagerequired')]; | |||||
return response()->json(['status' => 'error', 'errors' => $errors], 422); | |||||
} | |||||
if ($package->isDomain()) { | |||||
$errors = ['package' => \trans('validation.packageinvalid')]; | |||||
return response()->json(['status' => 'error', 'errors' => $errors], 422); | |||||
} | |||||
$user_name = !empty($settings['first_name']) ? $settings['first_name'] : ''; | $user_name = !empty($settings['first_name']) ? $settings['first_name'] : ''; | ||||
if (!empty($settings['last_name'])) { | if (!empty($settings['last_name'])) { | ||||
$user_name .= ' ' . $settings['last_name']; | $user_name .= ' ' . $settings['last_name']; | ||||
} | } | ||||
DB::beginTransaction(); | DB::beginTransaction(); | ||||
// Create user record | // Create user record | ||||
$user = User::create([ | $user = User::create([ | ||||
'name' => $user_name, | 'name' => $user_name, | ||||
'email' => $request->email, | 'email' => $request->email, | ||||
'password' => $request->password, | 'password' => $request->password, | ||||
]); | ]); | ||||
$owner->assignPackage($package, $user); | |||||
if (!empty($settings)) { | if (!empty($settings)) { | ||||
$user->setSettings($settings); | $user->setSettings($settings); | ||||
} | } | ||||
// TODO: Assign package | |||||
// Add aliases | |||||
if (!empty($request->aliases)) { | if (!empty($request->aliases)) { | ||||
$user->setAliases($request->aliases); | $user->setAliases($request->aliases); | ||||
} | } | ||||
DB::commit(); | DB::commit(); | ||||
return response()->json([ | return response()->json([ | ||||
'status' => 'success', | 'status' => 'success', | ||||
Show All 12 Lines | // 'cost' => $ent->cost, | ||||
public function update(Request $request, $id) | public function update(Request $request, $id) | ||||
{ | { | ||||
$user = User::find($id); | $user = User::find($id); | ||||
if (empty($user)) { | if (empty($user)) { | ||||
return $this->errorResponse(404); | return $this->errorResponse(404); | ||||
} | } | ||||
$current_user = $this->guard()->user(); | |||||
// TODO: Decide what attributes a user can change on his own profile | // TODO: Decide what attributes a user can change on his own profile | ||||
if (!$this->guard()->user()->canUpdate($user)) { | if (!$current_user->canUpdate($user)) { | ||||
return $this->errorResponse(403); | return $this->errorResponse(403); | ||||
} | } | ||||
if ($error_response = $this->validateUserRequest($request, $user, $settings)) { | if ($error_response = $this->validateUserRequest($request, $user, $settings)) { | ||||
return $error_response; | return $error_response; | ||||
} | } | ||||
// Entitlements, only controller can do that | |||||
if ($request->skus !== null && !$current_user->canDelete($user)) { | |||||
return $this->errorResponse(422, "You have no permission to change entitlements"); | |||||
} | |||||
DB::beginTransaction(); | DB::beginTransaction(); | ||||
$this->updateEntitlements($user, $request->skus); | |||||
if (!empty($settings)) { | if (!empty($settings)) { | ||||
$user->setSettings($settings); | $user->setSettings($settings); | ||||
} | } | ||||
// Update user password | |||||
if (!empty($request->password)) { | if (!empty($request->password)) { | ||||
$user->password = $request->password; | $user->password = $request->password; | ||||
$user->save(); | $user->save(); | ||||
} | } | ||||
// Update aliases | |||||
if (isset($request->aliases)) { | if (isset($request->aliases)) { | ||||
$user->setAliases($request->aliases); | $user->setAliases($request->aliases); | ||||
} | } | ||||
// TODO: Make sure that UserUpdate job is created in case of entitlements update | |||||
// and no password change. So, for example quota change is applied to LDAP | |||||
// TODO: Review use of $user->save() in the above context | |||||
DB::commit(); | DB::commit(); | ||||
return response()->json([ | return response()->json([ | ||||
'status' => 'success', | 'status' => 'success', | ||||
'message' => __('app.user-update-success'), | 'message' => __('app.user-update-success'), | ||||
]); | ]); | ||||
} | } | ||||
/** | /** | ||||
* Get the guard to be used during authentication. | * Get the guard to be used during authentication. | ||||
* | * | ||||
* @return \Illuminate\Contracts\Auth\Guard | * @return \Illuminate\Contracts\Auth\Guard | ||||
*/ | */ | ||||
public function guard() | public function guard() | ||||
{ | { | ||||
return Auth::guard(); | return Auth::guard(); | ||||
} | } | ||||
/** | /** | ||||
* Update user entitlements. | |||||
* | |||||
* @param \App\User $user The user | |||||
* @param array|null $skus Set of SKUs for the user | |||||
*/ | |||||
protected function updateEntitlements(User $user, $skus) | |||||
{ | |||||
if (!is_array($skus)) { | |||||
return; | |||||
} | |||||
// Existing SKUs | |||||
// FIXME: Is there really no query builder method to get result indexed | |||||
// by some column or primary key? | |||||
$all_skus = Sku::all()->mapWithKeys(function ($sku) { | |||||
return [$sku->id => $sku]; | |||||
}); | |||||
// Existing user entitlements | |||||
// Note: We sort them by cost, so e.g. for storage we get these free first | |||||
$entitlements = $user->entitlements()->orderBy('cost')->get(); | |||||
// Go through existing entitlements and remove those no longer needed | |||||
foreach ($entitlements as $ent) { | |||||
$sku_id = $ent->sku_id; | |||||
if (array_key_exists($sku_id, $skus)) { | |||||
// An existing entitlement exists on the requested list | |||||
$skus[$sku_id] -= 1; | |||||
if ($skus[$sku_id] < 0) { | |||||
$ent->delete(); | |||||
} | |||||
} elseif ($all_skus[$sku_id]->handler_class != \App\Handlers\Mailbox::class) { | |||||
// An existing entitlement does not exists on the requested list | |||||
// Never delete 'mailbox' SKU | |||||
$ent->delete(); | |||||
} | |||||
} | |||||
// Add missing entitlements | |||||
foreach ($skus as $sku_id => $count) { | |||||
if ($count > 0 && $all_skus->has($sku_id)) { | |||||
$user->assignSku($all_skus[$sku_id], $count); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Create a response data array for specified user. | * Create a response data array for specified user. | ||||
* | * | ||||
* @param \App\User $user User object | * @param \App\User $user User object | ||||
* | * | ||||
* @return array Response data | * @return array Response data | ||||
*/ | */ | ||||
protected function userResponse(User $user): array | protected function userResponse(User $user): array | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 173 Lines • Show Last 20 Lines |