Changeset View
Changeset View
Standalone View
Standalone View
src/app/Http/Controllers/API/V4/UsersController.php
Show First 20 Lines • Show All 548 Lines • ▼ Show 20 Lines | protected function validateUserRequest(Request $request, $user, &$settings = []) | ||||
$controller = $user ? $user->wallet()->owner : $this->guard()->user(); | $controller = $user ? $user->wallet()->owner : $this->guard()->user(); | ||||
// For new user validate email address | // For new user validate email address | ||||
if (empty($user)) { | if (empty($user)) { | ||||
$email = $request->email; | $email = $request->email; | ||||
if (empty($email)) { | if (empty($email)) { | ||||
$errors['email'] = \trans('validation.required', ['attribute' => 'email']); | $errors['email'] = \trans('validation.required', ['attribute' => 'email']); | ||||
} elseif ($error = self::validateEmail($email, $controller, false)) { | } elseif ($error = self::validateEmail($email, $controller)) { | ||||
$errors['email'] = $error; | $errors['email'] = $error; | ||||
} | } | ||||
} | } | ||||
// Validate aliases input | // Validate aliases input | ||||
if (isset($request->aliases)) { | if (isset($request->aliases)) { | ||||
$aliases = []; | $aliases = []; | ||||
$existing_aliases = $user ? $user->aliases()->get()->pluck('alias')->toArray() : []; | $existing_aliases = $user ? $user->aliases()->get()->pluck('alias')->toArray() : []; | ||||
foreach ($request->aliases as $idx => $alias) { | foreach ($request->aliases as $idx => $alias) { | ||||
if (is_string($alias) && !empty($alias)) { | if (is_string($alias) && !empty($alias)) { | ||||
// Alias cannot be the same as the email address (new user) | // Alias cannot be the same as the email address (new user) | ||||
if (!empty($email) && Str::lower($alias) == Str::lower($email)) { | if (!empty($email) && Str::lower($alias) == Str::lower($email)) { | ||||
continue; | continue; | ||||
} | } | ||||
// validate new aliases | // validate new aliases | ||||
if ( | if ( | ||||
!in_array($alias, $existing_aliases) | !in_array($alias, $existing_aliases) | ||||
&& ($error = self::validateEmail($alias, $controller, true)) | && ($error = self::validateAlias($alias, $controller)) | ||||
) { | ) { | ||||
if (!isset($errors['aliases'])) { | if (!isset($errors['aliases'])) { | ||||
$errors['aliases'] = []; | $errors['aliases'] = []; | ||||
} | } | ||||
$errors['aliases'][$idx] = $error; | $errors['aliases'][$idx] = $error; | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | public static function execProcessStep(User $user, string $step): ?bool | ||||
} catch (\Exception $e) { | } catch (\Exception $e) { | ||||
\Log::error($e); | \Log::error($e); | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Email address (login or alias) validation | * Email address validation for use as a user mailbox (login). | ||||
* | * | ||||
* @param string $email Email address | * @param string $email Email address | ||||
* @param \App\User $user The account owner | * @param \App\User $user The account owner | ||||
* @param bool $is_alias The email is an alias | |||||
* | * | ||||
* @return string Error message on validation error | * @return ?string Error message on validation error | ||||
*/ | */ | ||||
public static function validateEmail( | public static function validateEmail(string $email, \App\User $user): ?string | ||||
string $email, | { | ||||
\App\User $user, | if (strpos($email, '@') === false) { | ||||
bool $is_alias = false | return \trans('validation.entryinvalid', ['attribute' => 'email']); | ||||
): ?string { | } | ||||
$attribute = $is_alias ? 'alias' : 'email'; | |||||
list($login, $domain) = explode('@', Str::lower($email)); | |||||
if (strlen($login) === 0 || strlen($domain) === 0) { | |||||
return \trans('validation.entryinvalid', ['attribute' => 'email']); | |||||
} | |||||
// Check if domain exists | |||||
$domain = Domain::where('namespace', $domain)->first(); | |||||
if (empty($domain)) { | |||||
return \trans('validation.domaininvalid'); | |||||
} | |||||
// Validate login part alone | |||||
$v = Validator::make( | |||||
['email' => $login], | |||||
['email' => ['required', new UserEmailLocal(!$domain->isPublic())]] | |||||
); | |||||
if ($v->fails()) { | |||||
return $v->errors()->toArray()['email'][0]; | |||||
} | |||||
// Check if it is one of domains available to the user | |||||
$domains = \collect($user->domains())->pluck('namespace')->all(); | |||||
if (!in_array($domain->namespace, $domains)) { | |||||
return \trans('validation.entryexists', ['attribute' => 'domain']); | |||||
} | |||||
// Check if a user with specified address already exists | |||||
if (User::emailExists($email)) { | |||||
// TODO: Allow force-delete if this is a deleted user in the same custom domain | |||||
return \trans('validation.entryexists', ['attribute' => 'email']); | |||||
} | |||||
// Check if an alias with specified address already exists. | |||||
if (User::aliasExists($email)) { | |||||
return \trans('validation.entryexists', ['attribute' => 'email']); | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Email address validation for use as an alias. | |||||
* | |||||
* @param string $email Email address | |||||
* @param \App\User $user The account owner | |||||
* | |||||
* @return ?string Error message on validation error | |||||
*/ | |||||
public static function validateAlias(string $email, \App\User $user): ?string | |||||
{ | |||||
if (strpos($email, '@') === false) { | if (strpos($email, '@') === false) { | ||||
return \trans('validation.entryinvalid', ['attribute' => $attribute]); | return \trans('validation.entryinvalid', ['attribute' => 'alias']); | ||||
} | } | ||||
list($login, $domain) = explode('@', Str::lower($email)); | list($login, $domain) = explode('@', Str::lower($email)); | ||||
if (strlen($login) === 0 || strlen($domain) === 0) { | if (strlen($login) === 0 || strlen($domain) === 0) { | ||||
return \trans('validation.entryinvalid', ['attribute' => $attribute]); | return \trans('validation.entryinvalid', ['attribute' => 'alias']); | ||||
} | } | ||||
// Check if domain exists | // Check if domain exists | ||||
$domain = Domain::where('namespace', $domain)->first(); | $domain = Domain::where('namespace', $domain)->first(); | ||||
if (empty($domain)) { | if (empty($domain)) { | ||||
return \trans('validation.domaininvalid'); | return \trans('validation.domaininvalid'); | ||||
} | } | ||||
// Validate login part alone | // Validate login part alone | ||||
$v = Validator::make( | $v = Validator::make( | ||||
[$attribute => $login], | ['alias' => $login], | ||||
[$attribute => ['required', new UserEmailLocal(!$domain->isPublic())]] | ['alias' => ['required', new UserEmailLocal(!$domain->isPublic())]] | ||||
); | ); | ||||
if ($v->fails()) { | if ($v->fails()) { | ||||
return $v->errors()->toArray()[$attribute][0]; | return $v->errors()->toArray()['alias'][0]; | ||||
} | } | ||||
// Check if it is one of domains available to the user | // Check if it is one of domains available to the user | ||||
$domains = \collect($user->domains())->pluck('namespace')->all(); | $domains = \collect($user->domains())->pluck('namespace')->all(); | ||||
if (!in_array($domain->namespace, $domains)) { | if (!in_array($domain->namespace, $domains)) { | ||||
return \trans('validation.entryexists', ['attribute' => 'domain']); | return \trans('validation.entryexists', ['attribute' => 'domain']); | ||||
} | } | ||||
// Check if a user/alias with specified address already exists | // Check if a user with specified address already exists | ||||
if ($existing_user = User::emailExists($email, true)) { | |||||
// Allow an alias in a custom domain to an address that was a user before | |||||
if ($domain->isPublic() || !$existing_user->trashed()) { | |||||
return \trans('validation.entryexists', ['attribute' => 'alias']); | |||||
} | |||||
} | |||||
// Check if an alias with specified address already exists | |||||
if (User::aliasExists($email)) { | |||||
// Allow assigning the same alias to a user in the same group account, | // Allow assigning the same alias to a user in the same group account, | ||||
// but only for non-public domains | // but only for non-public domains | ||||
// Allow an alias in a custom domain to an address that was a user before | if ($domain->isPublic()) { | ||||
if ($exists = User::emailExists($email, true, $alias_exists, $is_alias && !$domain->isPublic())) { | return \trans('validation.entryexists', ['attribute' => 'alias']); | ||||
if ( | |||||
!$is_alias | |||||
|| !$alias_exists | |||||
|| $domain->isPublic() | |||||
|| $exists->wallet()->user_id != $user->id | |||||
) { | |||||
return \trans('validation.entryexists', ['attribute' => $attribute]); | |||||
} | } | ||||
} | } | ||||
return null; | return null; | ||||
} | } | ||||
} | } |