Changeset View
Changeset View
Standalone View
Standalone View
src/app/Http/Controllers/API/V4/UsersController.php
<?php | <?php | ||||
namespace App\Http\Controllers\API\V4; | namespace App\Http\Controllers\API\V4; | ||||
use App\Http\Controllers\Controller; | use App\Http\Controllers\Controller; | ||||
use App\Domain; | use App\Domain; | ||||
use App\Group; | use App\Group; | ||||
use App\Rules\UserEmailDomain; | use App\Rules\UserEmailDomain; | ||||
use App\Rules\UserEmailLocal; | use App\Rules\UserEmailLocal; | ||||
use App\Sku; | use App\Sku; | ||||
use App\User; | use App\User; | ||||
use Carbon\Carbon; | |||||
use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||
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 | ||||
{ | { | ||||
/** @const array List of user setting keys available for modification in UI */ | /** @const array List of user setting keys available for modification in UI */ | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | public function index() | ||||
if (count($result) > $pageSize) { | if (count($result) > $pageSize) { | ||||
$result->pop(); | $result->pop(); | ||||
$hasMore = true; | $hasMore = true; | ||||
} | } | ||||
// Process the result | // Process the result | ||||
$result = $result->map( | $result = $result->map( | ||||
function ($user) { | function ($user) { | ||||
$data = $user->toArray(); | return $this->userToClient($user); | ||||
$data = array_merge($data, self::userStatuses($user)); | |||||
return $data; | |||||
} | } | ||||
); | ); | ||||
$result = [ | $result = [ | ||||
'list' => $result, | 'list' => $result, | ||||
'count' => count($result), | 'count' => count($result), | ||||
'hasMore' => $hasMore, | 'hasMore' => $hasMore, | ||||
]; | ]; | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | public function status($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 = self::statusInfo($user); | $response = $this->processStateUpdate($user); | ||||
if (!empty(request()->input('refresh'))) { | |||||
$updated = false; | |||||
$async = false; | |||||
$last_step = 'none'; | |||||
foreach ($response['process'] as $idx => $step) { | |||||
$last_step = $step['label']; | |||||
if (!$step['state']) { | |||||
$exec = $this->execProcessStep($user, $step['label']); | |||||
if (!$exec) { | |||||
if ($exec === null) { | |||||
$async = true; | |||||
} | |||||
break; | |||||
} | |||||
$updated = true; | |||||
} | |||||
} | |||||
if ($updated) { | |||||
$response = self::statusInfo($user); | |||||
} | |||||
$success = $response['isReady']; | |||||
$suffix = $success ? 'success' : 'error-' . $last_step; | |||||
$response['status'] = $success ? 'success' : 'error'; | |||||
$response['message'] = \trans('app.process-' . $suffix); | |||||
if ($async && !$success) { | |||||
$response['processState'] = 'waiting'; | |||||
$response['status'] = 'success'; | |||||
$response['message'] = \trans('app.process-async'); | |||||
} | |||||
} | |||||
$response = array_merge($response, self::userStatuses($user)); | $response = array_merge($response, self::userStatuses($user)); | ||||
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 | ||||
* | * | ||||
* @return array Status information | * @return array Status information | ||||
*/ | */ | ||||
public static function statusInfo(User $user): array | public static function statusInfo(User $user): array | ||||
{ | { | ||||
$process = []; | $process = self::processStateInfo( | ||||
$steps = [ | $user, | ||||
[ | |||||
'user-new' => true, | 'user-new' => true, | ||||
'user-ldap-ready' => $user->isLdapReady(), | 'user-ldap-ready' => $user->isLdapReady(), | ||||
'user-imap-ready' => $user->isImapReady(), | 'user-imap-ready' => $user->isImapReady(), | ||||
]; | ] | ||||
); | |||||
// Create a process check list | |||||
foreach ($steps as $step_name => $state) { | |||||
$step = [ | |||||
'label' => $step_name, | |||||
'title' => \trans("app.process-{$step_name}"), | |||||
'state' => $state, | |||||
]; | |||||
$process[] = $step; | |||||
} | |||||
list ($local, $domain) = explode('@', $user->email); | |||||
$domain = Domain::where('namespace', $domain)->first(); | |||||
// If that is not a public domain, add domain specific steps | |||||
if ($domain && !$domain->isPublic()) { | |||||
$domain_status = DomainsController::statusInfo($domain); | |||||
$process = array_merge($process, $domain_status['process']); | |||||
} | |||||
$all = count($process); | |||||
$checked = count(array_filter($process, function ($v) { | |||||
return $v['state']; | |||||
})); | |||||
$state = $all === $checked ? 'done' : 'running'; | |||||
// After 180 seconds assume the process is in failed state, | |||||
// this should unlock the Refresh button in the UI | |||||
if ($all !== $checked && $user->created_at->diffInSeconds(Carbon::now()) > 180) { | |||||
$state = 'failed'; | |||||
} | |||||
// Check if the user is a controller of his wallet | // Check if the user is a controller of his wallet | ||||
$isController = $user->canDelete($user); | $isController = $user->canDelete($user); | ||||
$hasCustomDomain = $user->wallet()->entitlements() | $hasCustomDomain = $user->wallet()->entitlements() | ||||
->where('entitleable_type', Domain::class) | ->where('entitleable_type', Domain::class) | ||||
->count() > 0; | ->count() > 0; | ||||
// Get user's entitlements titles | // Get user's entitlements titles | ||||
$skus = $user->entitlements()->select('skus.title') | $skus = $user->entitlements()->select('skus.title') | ||||
->join('skus', 'skus.id', '=', 'entitlements.sku_id') | ->join('skus', 'skus.id', '=', 'entitlements.sku_id') | ||||
->get() | ->get() | ||||
->pluck('title') | ->pluck('title') | ||||
->sort() | ->sort() | ||||
->unique() | ->unique() | ||||
->values() | ->values() | ||||
->all(); | ->all(); | ||||
return [ | $result = [ | ||||
'skus' => $skus, | 'skus' => $skus, | ||||
// TODO: This will change when we enable all users to create domains | // TODO: This will change when we enable all users to create domains | ||||
'enableDomains' => $isController && $hasCustomDomain, | 'enableDomains' => $isController && $hasCustomDomain, | ||||
// TODO: Make 'enableDistlists' working for wallet controllers that aren't account owners | // TODO: Make 'enableDistlists' working for wallet controllers that aren't account owners | ||||
'enableDistlists' => $isController && $hasCustomDomain && in_array('distlist', $skus), | 'enableDistlists' => $isController && $hasCustomDomain && in_array('distlist', $skus), | ||||
'enableUsers' => $isController, | 'enableUsers' => $isController, | ||||
'enableWallets' => $isController, | 'enableWallets' => $isController, | ||||
'process' => $process, | |||||
'processState' => $state, | |||||
'isReady' => $all === $checked, | |||||
]; | ]; | ||||
return array_merge($process, $result); | |||||
} | } | ||||
/** | /** | ||||
* Create a new user record. | * Create a new user record. | ||||
* | * | ||||
* @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 | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | class UsersController extends Controller | ||||
* 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 | ||||
*/ | */ | ||||
public static function userResponse(User $user): array | public static function userResponse(User $user): array | ||||
{ | { | ||||
$response = $user->toArray(); | $response = self::userToClient($user, true); | ||||
// Settings | // Settings | ||||
$response['settings'] = []; | $response['settings'] = []; | ||||
foreach ($user->settings()->whereIn('key', self::USER_SETTINGS)->get() as $item) { | foreach ($user->settings()->whereIn('key', self::USER_SETTINGS)->get() as $item) { | ||||
$response['settings'][$item->key] = $item->value; | $response['settings'][$item->key] = $item->value; | ||||
} | } | ||||
// Aliases | // Aliases | ||||
$response['aliases'] = []; | $response['aliases'] = []; | ||||
foreach ($user->aliases as $item) { | foreach ($user->aliases as $item) { | ||||
$response['aliases'][] = $item->alias; | $response['aliases'][] = $item->alias; | ||||
} | } | ||||
// Status info | // Status info | ||||
$response['statusInfo'] = self::statusInfo($user); | $response['statusInfo'] = self::statusInfo($user); | ||||
$response = array_merge($response, self::userStatuses($user)); | |||||
// Add more info to the wallet object output | // Add more info to the wallet object output | ||||
$map_func = function ($wallet) use ($user) { | $map_func = function ($wallet) use ($user) { | ||||
$result = $wallet->toArray(); | $result = $wallet->toArray(); | ||||
if ($wallet->discount) { | if ($wallet->discount) { | ||||
$result['discount'] = $wallet->discount->discount; | $result['discount'] = $wallet->discount->discount; | ||||
$result['discount_description'] = $wallet->discount->description; | $result['discount_description'] = $wallet->discount->description; | ||||
} | } | ||||
Show All 30 Lines | protected static function userStatuses(User $user): array | ||||
'isLdapReady' => $user->isLdapReady(), | 'isLdapReady' => $user->isLdapReady(), | ||||
'isSuspended' => $user->isSuspended(), | 'isSuspended' => $user->isSuspended(), | ||||
'isActive' => $user->isActive(), | 'isActive' => $user->isActive(), | ||||
'isDeleted' => $user->isDeleted() || $user->trashed(), | 'isDeleted' => $user->isDeleted() || $user->trashed(), | ||||
]; | ]; | ||||
} | } | ||||
/** | /** | ||||
* Prepare a user information for the UI | |||||
* | |||||
* @param \App\User $user User object | |||||
* @param bool $full Include all user properties | |||||
* | |||||
* @return array User data as an array | |||||
*/ | |||||
protected static function userToClient(User $user, bool $full = false): array | |||||
{ | |||||
if ($full) { | |||||
$response = $user->toArray(); | |||||
} else { | |||||
$response = [ | |||||
'id' => $user->id, | |||||
'email' => $user->email, | |||||
'status' => $user->status, | |||||
]; | |||||
} | |||||
$response = array_merge($response, self::userStatuses($user)); | |||||
return $response; | |||||
} | |||||
/** | |||||
* Validate user input | * Validate user input | ||||
* | * | ||||
* @param \Illuminate\Http\Request $request The API request. | * @param \Illuminate\Http\Request $request The API request. | ||||
* @param \App\User|null $user User identifier | * @param \App\User|null $user User identifier | ||||
* @param array $settings User settings (from the request) | * @param array $settings User settings (from the request) | ||||
* | * | ||||
* @return \Illuminate\Http\JsonResponse|null The error response on error | * @return \Illuminate\Http\JsonResponse|null The error response on error | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 282 Lines • Show Last 20 Lines |