mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-28 06:20:14 +00:00
feat: allow using existing deSEC account by supplying a password
Agent-Logs-Url: https://github.com/nextcloud/all-in-one/sessions/57f233da-439b-4992-888c-82fad2dfa2cc Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
b0b997ac42
commit
24f8a126cb
@@ -15,9 +15,10 @@ readonly class DesecController {
|
||||
|
||||
public function Register(Request $request, Response $response, array $args): Response {
|
||||
try {
|
||||
$email = (string)($request->getParsedBody()['desec_email'] ?? '');
|
||||
$slug = (string)($request->getParsedBody()['desec_slug'] ?? '');
|
||||
$this->desecManager->register($email, $slug);
|
||||
$email = (string)($request->getParsedBody()['desec_email'] ?? '');
|
||||
$slug = (string)($request->getParsedBody()['desec_slug'] ?? '');
|
||||
$password = (string)($request->getParsedBody()['desec_password'] ?? '');
|
||||
$this->desecManager->register($email, $slug, $password);
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
} catch (\Exception $ex) {
|
||||
$response->getBody()->write($ex->getMessage());
|
||||
|
||||
@@ -29,9 +29,14 @@ class DesecManager {
|
||||
* Full registration flow: validates inputs, creates an account if needed,
|
||||
* registers the domain, enables required containers, and updates the DNS record.
|
||||
*
|
||||
* When $password is non-empty the user is logging into an existing deSEC account
|
||||
* rather than creating a new one. When $password is empty a new account is created
|
||||
* with a randomly generated password (unless an account was already registered in a
|
||||
* previous attempt).
|
||||
*
|
||||
* @throws \Exception on any validation or API error
|
||||
*/
|
||||
public function register(string $email, string $slug): void {
|
||||
public function register(string $email, string $slug, string $password = ''): void {
|
||||
if ($this->configurationManager->domain !== '') {
|
||||
throw new \Exception('A domain is already configured. Reset the AIO instance first to register a new domain.');
|
||||
}
|
||||
@@ -41,19 +46,23 @@ class DesecManager {
|
||||
? $this->configurationManager->desecToken
|
||||
: null;
|
||||
|
||||
$validatedEmail = null;
|
||||
if (!$accountAlreadyRegistered) {
|
||||
$validatedEmail = $this->validateEmail($email);
|
||||
}
|
||||
|
||||
$validatedSlug = $this->validateSlug($slug);
|
||||
|
||||
if (!$accountAlreadyRegistered) {
|
||||
// 24 random bytes → 48-char hex password; satisfies deSEC's minimum length
|
||||
// and lets the user log in at desec.io if they ever need to.
|
||||
$password = bin2hex(random_bytes(24));
|
||||
$token = $this->registerAccount($validatedEmail, $password);
|
||||
$this->saveAccountCredentials($token, $password, $validatedEmail);
|
||||
$validatedEmail = $this->validateEmail($email);
|
||||
$validatedPassword = trim($password);
|
||||
|
||||
if ($validatedPassword !== '') {
|
||||
// The user supplied their existing deSEC password — log in instead of registering.
|
||||
$token = $this->loginAccount($validatedEmail, $validatedPassword);
|
||||
$this->saveAccountCredentials($token, $validatedPassword, $validatedEmail);
|
||||
} else {
|
||||
// 24 random bytes → 48-char hex password; satisfies deSEC's minimum length
|
||||
// and lets the user log in at desec.io if they ever need to.
|
||||
$generatedPassword = bin2hex(random_bytes(24));
|
||||
$token = $this->registerAccount($validatedEmail, $generatedPassword);
|
||||
$this->saveAccountCredentials($token, $generatedPassword, $validatedEmail);
|
||||
}
|
||||
}
|
||||
|
||||
$domain = $this->registerDomain($token, $validatedSlug);
|
||||
@@ -114,7 +123,7 @@ class DesecManager {
|
||||
if (is_array($data) && isset($data['email'])) {
|
||||
throw new \Exception(
|
||||
'This email address is already registered at deSEC. '
|
||||
. 'Please log in at https://desec.io to retrieve your token and set up your domain manually.',
|
||||
. 'If this is your account, please enter your deSEC password in the password field and try again.',
|
||||
);
|
||||
}
|
||||
throw new \Exception('Registration at deSEC failed (HTTP 400): ' . $body);
|
||||
@@ -132,6 +141,39 @@ class DesecManager {
|
||||
return $data['token']['token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates with an existing deSEC account and returns the API token issued for it.
|
||||
*
|
||||
* @throws \Exception on invalid credentials, network failure, or an unexpected HTTP response
|
||||
*/
|
||||
public function loginAccount(string $email, string $password): string {
|
||||
try {
|
||||
$res = $this->guzzleClient->post(self::DESEC_API_BASE . '/auth/login/', [
|
||||
'json' => ['email' => $email, 'password' => $password],
|
||||
]);
|
||||
} catch (TransferException $e) {
|
||||
throw new \Exception('Could not reach the deSEC API: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$code = $res->getStatusCode();
|
||||
$body = $res->getBody()->getContents();
|
||||
|
||||
if ($code === 400 || $code === 403) {
|
||||
throw new \Exception('Could not log in to deSEC: invalid email address or password.');
|
||||
}
|
||||
|
||||
if ($code !== 200 && $code !== 201) {
|
||||
throw new \Exception('Unexpected response from deSEC during login (HTTP ' . $code . '): ' . $body);
|
||||
}
|
||||
|
||||
$data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
||||
if (!is_array($data) || !isset($data['token']) || !is_string($data['token'])) {
|
||||
throw new \Exception('Could not extract the API token from the deSEC login response. Please try again.');
|
||||
}
|
||||
|
||||
return $data['token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a dedyn.io domain for the authenticated account.
|
||||
* When $slug is empty a random 10-character slug is tried up to MAX_SLUG_ATTEMPTS times.
|
||||
|
||||
@@ -146,10 +146,12 @@
|
||||
</form>
|
||||
{% else %}
|
||||
<p>Please enter your email address. You can also enter a desired subdomain slug (the part before <code>.dedyn.io</code>); leave it blank for a random one.</p>
|
||||
<p>If you already have a deSEC account for this email address, enter your deSEC password in the optional password field below to log in with it instead of creating a new account.</p>
|
||||
<form method="POST" action="api/desec/register" class="xhr">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="email" name="desec_email" placeholder="your@email.com" required />
|
||||
<input type="password" name="desec_password" placeholder="deSEC password (only if already registered)" autocomplete="current-password" />
|
||||
<input type="text" name="desec_slug" placeholder="my-nextcloud (optional)" pattern="[a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?" title="Only lowercase letters, digits and hyphens (1–63 characters). No leading or trailing hyphen." />
|
||||
<input type="submit" value="Register free domain via deSEC" />
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user