Class AccountEmailChange
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
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceThe delivery step of a mail:Mail::queuein the server, a fake in the tests.static enumWhy a new address is refused.Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longHow long a pending change is valid: the life of its verification link, 72 hours.Method Summary
Modifier and TypeMethodDescriptionstatic voidclearPending(Connection conn, BasicUserInfo bui) Removes a pending change, no commit.static StringcompletePending(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.static booleanisExternal(BasicUserInfo bui) Checks if an account is an external Sign In Provider's: its stored hash starts with "EXT:".static booleanChecks 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.static booleanisVerified(BasicUserInfo bui) Checks if the registered e-mail address of a user is verified: the detailIZS-EmailVerifynames the address with the code 3.static StringpendingAddress(BasicUserInfo bui, boolean reload, long now) Gets the address a pending change names.static AuthenticatedUserrefreshed(Connection conn, long uid) 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 cachedAuthenticatedUser- a signed-in session, ServerAdmin's list - sees the new address.static AccountEmailChange.Refusalrefusal(Connection conn, BasicUserInfo bui, String newEmail) The rules of a new address, in the order they are checked: the form, the account's kind, the name that is the address.static voidwritePending(Connection conn, BasicUserInfo bui, String newEmail, long now) Writes a pending change, replacing one that is pending, no commit.
Field Details
VALIDITY_MS
public static final long VALIDITY_MSHow long a pending change is valid: the life of its verification link, 72 hours.- See Also:
Method Details
isVerified
Checks if the registered e-mail address of a user is verified: the detailIZS-EmailVerifynames 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
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
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
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 cachedAuthenticatedUser- 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).