Ctrl K
ComunidadGuías…

view/signup.html

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
{{define "content"}}
<form class="auth-card" method="POST" action="{{authURL "/signup"}}" data-auth-mode="{{.AuthMode}}" id="signup-form">
  <div class="auth-header">
    {{template "logo" .}}
    <h1 class="auth-title">{{.ThemeTitle}}</h1>
    {{if .ThemeTagline}}<p class="auth-tagline">{{.ThemeTagline}}</p>{{end}}
  </div>
  {{ .csrfField }}
  <input type="hidden" name="state" value="{{.State}}" />
  <input type="hidden" name="redirect_uri" value="{{.RedirectURI}}" />
  <input type="hidden" name="client_id" value="{{.ClientID}}" />
  <input type="hidden" name="scope" value="{{.Scope}}" />
  <input type="hidden" name="nonce" value="{{.Nonce}}" />
  <input type="hidden" name="code_challenge" value="{{.CodeChallenge}}" />
  <input type="hidden" name="code_challenge_method" value="{{.CodeChallengeMethod}}" />
  <input type="hidden" name="prompt" value="{{.Prompt}}" />
  <input type="hidden" name="max_age" value="{{.MaxAge}}" />
  <input type="hidden" name="authorize_sig" value="{{.AuthorizeSig}}" />
  <div class="auth-field">
    {{if eq .ProfileFieldEmail "is_username"}}
    <label class="auth-label" for="username">Email</label>
    <input class="auth-input" type="email" id="username" name="username" required autocomplete="email" />
    {{else}}
    <label class="auth-label" for="username">Username</label>
    <input class="auth-input" type="text" id="username" name="username" required autocomplete="username" />
    {{end}}
  </div>
  {{if or (and .RequireEmailVerification (ne .ProfileFieldEmail "is_username")) (eq .ProfileFieldEmail "required") (and (eq .ProfileFieldEmail "optional") .ShowOptionalFields)}}
  <div class="auth-field">
    <label class="auth-label" for="email">Email{{if or .RequireEmailVerification (eq .ProfileFieldEmail "required")}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="email" id="email" name="email" autocomplete="email" {{if or .RequireEmailVerification (eq .ProfileFieldEmail "required")}}required{{end}} />
  </div>
  {{end}}
  {{if or (eq .ProfileFieldGivenName "required") (and (eq .ProfileFieldGivenName "optional") .ShowOptionalFields)}}
  <div class="auth-field">
    <label class="auth-label" for="given_name">First Name{{if eq .ProfileFieldGivenName "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="given_name" name="given_name" autocomplete="given-name" {{if eq .ProfileFieldGivenName "required"}}required{{end}} />
  </div>
  {{end}}
  {{if or (eq .ProfileFieldFamilyName "required") (and (eq .ProfileFieldFamilyName "optional") .ShowOptionalFields)}}
  <div class="auth-field">
    <label class="auth-label" for="family_name">Last Name{{if eq .ProfileFieldFamilyName "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="family_name" name="family_name" autocomplete="family-name" {{if eq .ProfileFieldFamilyName "required"}}required{{end}} />
  </div>
  {{end}}
  {{if or (eq .ProfileFieldPhone "required") (and (eq .ProfileFieldPhone "optional") .ShowOptionalFields)}}
  <div class="auth-field">
    <label class="auth-label" for="phone_number">Phone Number{{if eq .ProfileFieldPhone "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="tel" id="phone_number" name="phone_number" autocomplete="tel" {{if eq .ProfileFieldPhone "required"}}required{{end}} />
  </div>
  {{end}}
  {{if or (eq .ProfileFieldPicture "required") (and (eq .ProfileFieldPicture "optional") .ShowOptionalFields)}}
  <div class="auth-field">
    <label class="auth-label" for="picture">Profile Picture URL{{if eq .ProfileFieldPicture "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="url" id="picture" name="picture" autocomplete="photo" {{if eq .ProfileFieldPicture "required"}}required{{end}} />
  </div>
  {{end}}
  {{if or (eq .ProfileFieldAddress "required") (and (eq .ProfileFieldAddress "optional") .ShowOptionalFields)}}
  <div class="auth-field">
    <label class="auth-label" for="address_street">Street Address{{if eq .ProfileFieldAddress "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="address_street" name="address_street" autocomplete="street-address" {{if eq .ProfileFieldAddress "required"}}required{{end}} />
  </div>
  <div class="auth-field">
    <label class="auth-label" for="address_locality">City{{if eq .ProfileFieldAddress "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="address_locality" name="address_locality" autocomplete="address-level2" {{if eq .ProfileFieldAddress "required"}}required{{end}} />
  </div>
  <div class="auth-field">
    <label class="auth-label" for="address_region">State / Region{{if eq .ProfileFieldAddress "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="address_region" name="address_region" autocomplete="address-level1" {{if eq .ProfileFieldAddress "required"}}required{{end}} />
  </div>
  <div class="auth-field">
    <label class="auth-label" for="address_postal_code">Postal Code{{if eq .ProfileFieldAddress "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="address_postal_code" name="address_postal_code" autocomplete="postal-code" {{if eq .ProfileFieldAddress "required"}}required{{end}} />
  </div>
  <div class="auth-field">
    <label class="auth-label" for="address_country">Country{{if eq .ProfileFieldAddress "required"}} <span style="color:var(--color-danger-bg)">*</span>{{end}}</label>
    <input class="auth-input" type="text" id="address_country" name="address_country" autocomplete="country-name" {{if eq .ProfileFieldAddress "required"}}required{{end}} />
  </div>
  {{end}}
  {{if ne .AuthMode "passkey_only"}}
  <div id="password-fields">
    <div class="auth-field">
      <label class="auth-label" for="password">Password</label>
      <input class="auth-input" type="password" id="password" name="password" required autocomplete="new-password" />
    </div>
    <div class="auth-field">
      <label class="auth-label" for="confirm_password">Confirm Password</label>
      <input class="auth-input" type="password" id="confirm_password" name="confirm_password" required autocomplete="new-password" />
    </div>
  </div>
  {{end}}
  {{if eq .AuthMode "password_and_passkey"}}
  <div class="auth-checkbox">
    <input type="checkbox" id="use-passkey" />
    <label for="use-passkey">Use passkey instead of password</label>
  </div>
  {{end}}
  {{if .Error}}
  <div class="auth-error" role="alert" id="signup-error">{{.Error}}</div>
  {{else}}
  <div class="auth-error" role="alert" id="signup-error" style="display:none"></div>
  {{end}}
  <button class="auth-btn" type="submit" id="signup-btn">
    {{if eq .AuthMode "passkey_only"}}Signup with Passkey{{else}}Create Account{{end}}
  </button>
  <div class="auth-link">Already have an account? <a href="{{authURL "/authorize"}}?response_type=code&client_id={{.ClientID}}&redirect_uri={{.RedirectURI}}&state={{.State}}&scope={{.Scope}}&nonce={{.Nonce}}&code_challenge={{.CodeChallenge}}&code_challenge_method={{.CodeChallengeMethod}}&prompt={{.LoginPrompt}}&max_age={{.MaxAge}}">Log in</a></div>
</form>
{{end}}

{{define "scripts"}}
{{if ne .AuthMode "password"}}<script nonce="{{.CspNonce}}" src="{{authURL "/static/passkey.js"}}"></script>{{end}}
<script nonce="{{.CspNonce}}">
  function showPasskeyError(msg) {
    const el = document.getElementById('signup-error');
    el.textContent = msg;
    el.style.display = '';
  }
  function togglePasskeyMode(checkbox) {
    const pwFields = document.getElementById('password-fields');
    const btn = document.getElementById('signup-btn');
    const pwInput = document.getElementById('password');
    const confirmInput = document.getElementById('confirm_password');
    if (checkbox.checked) {
      pwFields.style.display = 'none';
      pwInput.required = false;
      confirmInput.required = false;
      btn.textContent = 'Signup with Passkey';
    } else {
      pwFields.style.display = 'flex';
      pwInput.required = true;
      confirmInput.required = true;
      btn.textContent = 'Create Account';
    }
  }
  async function startPasskeyRegistration() {
    const username = document.getElementById('username').value.trim();
    const emailEl = document.getElementById('email');
    const email = emailEl ? emailEl.value.trim() : '';
    document.getElementById('signup-error').style.display = 'none';
    const params = new URLSearchParams({
      username,
      email,
      redirect_uri: document.querySelector('[name=redirect_uri]').value,
      state: document.querySelector('[name=state]').value,
      client_id: document.querySelector('[name=client_id]').value,
      scope: document.querySelector('[name=scope]').value,
      nonce: document.querySelector('[name=nonce]').value,
      code_challenge: document.querySelector('[name=code_challenge]').value,
      code_challenge_method: document.querySelector('[name=code_challenge_method]').value,
      prompt: document.querySelector('[name=prompt]').value,
      max_age: document.querySelector('[name=max_age]').value,
      authorize_sig: document.querySelector('[name=authorize_sig]').value,
    });
    try {
      const beginResp = await fetch('{{authURL "/passkey/register/begin"}}?' + params.toString());
      const data = await beginResp.json();
      if (!beginResp.ok) { showPasskeyError(data.error || 'Failed to start registration'); return; }
      await doPasskeyRegister(data, '{{authURL ""}}');
    } catch (e) { showPasskeyError('Passkey error: ' + e.message); }
  }
  function handleSignupSubmit(event) {
    const authMode = document.querySelector('form').dataset.authMode;
    const usePasskey = authMode === 'passkey_only' ||
      (authMode === 'password_and_passkey' && document.getElementById('use-passkey')?.checked);
    if (usePasskey) {
      event.preventDefault();
      startPasskeyRegistration();
    }
  }
  (function() {
    var form = document.getElementById('signup-form');
    if (form) { form.addEventListener('submit', handleSignupSubmit); }
    var passkeyCheckbox = document.getElementById('use-passkey');
    if (passkeyCheckbox) { passkeyCheckbox.addEventListener('change', function() { togglePasskeyMode(this); }); }
  })();
</script>
{{end}}