Class AccountEmailChange

java.lang.Object
com.iizix.server.user.AccountEmailChange

public final class AccountEmailChange extends Object
The registered e-mail address of an account: its one write, the rules of a change, its verified state, and the change the user asks for and confirms by a link (CC-ACCOUNT-EMAIL-PASSWORD).

The one write. writeEmail(Connection, BasicUserInfo, String, boolean, long) is the only code that replaces IZS.USERS.email: it writes the column, the details IZS-Email and IZS-EmailVerify (code 3 for a verified address, 0 for one to verify), and removes a pending change. Two paths reach it: the user's confirmed link (completePending(BasicUserInfo, String, MailSender, AccountEmailChange.IMailStep, long), SE-1) and the administrator's change in ServerAdmin (AdminAccountChanges.setEmail(IAuthenticatedUser, BasicUserInfo, String, MailSender, AccountEmailChange.IMailStep, Function, AccountNotices.Context), AE-3). AuthenticatedUser.changeEmail, which switched an address at once on a password and had no caller, is gone.

The pending change (SE-1). IUserAuthenticationUI.requestEmailChange checks the new address and the password, writes the detail IBasicUserInfoDetailNames.DETAIL_EmailChange (newEmail,timestamp) and mails the verification link of the new address, sealed for that address and the user (EmailVerificationLink). When the link is opened, the server's verifier finds the pending change naming that address and makes it: the new address replaces the registered one, verified, a notice goes to the old address, and the detail is removed. A later request replaces the pending one; a pending change is void after VALIDITY_MS, the life of its link.

The verified state. An address is verified when the detail IZS-EmailVerify names it with the code 3 (isVerified(BasicUserInfo)): a changed address is unverified by itself.

No log line of this class carries a full address (EmailAddressForm.masked(String)).

Author:
Christopher Mindus
  • Field Details

    • VALIDITY_MS

      public static final long VALIDITY_MS
      How long a pending change is valid: the life of its verification link, 72 hours.
      See Also:
  • Method Details

    • isVerified

      public static boolean isVerified(BasicUserInfo bui)
      Checks if the registered e-mail address of a user is verified: the detail IZS-EmailVerify names the address with the code 3.
      Parameters:
      bui - The user.
      Returns:
      true when it is verified, and when the user has no address to verify; false otherwise and when the details cannot be read (logged).
    • isNameTheAddress

      public static boolean isNameTheAddress(BasicUserInfo bui)
      Checks if the user name of an account is its registered address (compared without regard to case): the address is then the sign-in name, and a change is a rename, out of scope.
      Parameters:
      bui - The user.
      Returns:
      true when the name is the address.
    • isExternal

      public static boolean isExternal(BasicUserInfo bui)
      Checks if an account is an external Sign In Provider's: its stored hash starts with "EXT:".
      Parameters:
      bui - The user.
      Returns:
      true for an external account.
    • refusal

      public static AccountEmailChange.Refusal refusal(Connection conn, BasicUserInfo bui, String newEmail) throws SQLException
      The rules of a new address, in the order they are checked: the form, the account's kind, the name that is the address. A shared address is allowed (EM-D-1, CC-FIX-SIGNIN-ACCOUNT-MAIL): several accounts may carry one address, and no rule here looks at the other accounts.
      Parameters:
      conn - The connection.
      bui - The user whose address would change.
      newEmail - The new address, trimmed.
      Returns:
      The refusal, or null when the address may be set.
      Throws:
      SQLException - For SQL errors.
    • pendingAddress

      public static String pendingAddress(BasicUserInfo bui, boolean reload, long now) throws SQLException
      Gets the address a pending change names.
      Parameters:
      bui - The user.
      reload - true to read the details from the database first, false for the cached ones.
      now - The current time.
      Returns:
      The new address, or null when no change is pending, when it has expired (the detail is then left for the next write to remove), or when the detail is malformed.
      Throws:
      SQLException - For SQL errors.
    • writePending

      public static void writePending(Connection conn, BasicUserInfo bui, String newEmail, long now) throws SQLException
      Writes a pending change, replacing one that is pending, no commit.
      Parameters:
      conn - The connection.
      bui - The user.
      newEmail - The new address, trimmed.
      now - The time of the request.
      Throws:
      SQLException - For SQL errors.
    • clearPending

      public static void clearPending(Connection conn, BasicUserInfo bui) throws SQLException
      Removes a pending change, no commit.
      Parameters:
      conn - The connection.
      bui - The user.
      Throws:
      SQLException - For SQL errors.
    • refreshed

      public static AuthenticatedUser refreshed(Connection conn, long uid) throws SQLException, NotFoundException
      Re-reads a user from the database after a committed write and puts the fresh information into the cached user, so that every holder of the cached AuthenticatedUser - a signed-in session, ServerAdmin's list - sees the new address.
      Parameters:
      conn - The connection.
      uid - The user ID.
      Returns:
      The cached user, refreshed.
      Throws:
      SQLException - For SQL errors.
      NotFoundException - If the user has been deleted.
    • completePending

      public static String completePending(BasicUserInfo bui, String email, MailSender sender, AccountEmailChange.IMailStep deliver, long now)
      Completes a pending change when a verification link of an address is opened: when the user has a pending change to that address (compared without regard to case), the new address replaces the registered one, verified, the change is committed and the cached user refreshed, and the old address is told; otherwise nothing is done.
      Parameters:
      bui - The user of the link.
      email - The address the link was sealed for.
      sender - The mail sender for the notice to the old address, null for none configured.
      deliver - The delivery step of the notice.
      now - The current time.
      Returns:
      The old address when the change was made ("" when the account had none), null when no change to that address was pending or the change could not be written (logged SEVERE).