Skip to content

Commit ee4451e

Browse files
vagishaclaude
andcommitted
Emailed the account owner when signup hits an existing address
* SignUpApiAction and BeginAction now email the owner of an already-registered address (new sendExistingAccountEmail helper) instead of doing nothing. Both signup paths now send an email, so response timing no longer reveals whether an account exists. * The existing account is never modified, and send failures are logged and swallowed so the response stays identical to a new signup. The email points the owner to the "Forgot your password?" reset flow. * Renamed the SignUpApiAction success status from USER_ADDED to SUCCESS, which was misleading in the existing-account case where no user is added. The external signup wiki form must key its success branch off SUCCESS. Co-Authored-By: Claude <[email protected]>
1 parent bd77688 commit ee4451e

1 file changed

Lines changed: 37 additions & 4 deletions

File tree

signup/src/org/labkey/signup/SignUpController.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.labkey.api.security.DbLoginService;
4848
import org.labkey.api.security.Group;
4949
import org.labkey.api.security.LoginManager;
50+
import org.labkey.api.security.LoginUrls;
5051
import org.labkey.api.security.RequiresLogin;
5152
import org.labkey.api.security.RequiresNoPermission;
5253
import org.labkey.api.security.RequiresPermission;
@@ -61,6 +62,7 @@
6162
import org.labkey.api.util.ButtonBuilder;
6263
import org.labkey.api.util.ConfigurationException;
6364
import org.labkey.api.util.DOM;
65+
import org.labkey.api.util.MailHelper;
6466
import org.labkey.api.util.PageFlowUtil;
6567
import org.labkey.api.util.URLHelper;
6668
import org.labkey.api.util.CsrfInput;
@@ -594,7 +596,8 @@ public boolean handlePost(SignupForm signupForm, BindException errors) throws Ex
594596
if (UserManager.userExists(email))
595597
{
596598
// Do not reveal whether an account already exists (avoids user enumeration).
597-
// Show the same "confirmation sent" response as a new signup, without sending an email.
599+
// Notify the real owner and show the same "confirmation sent" response as a new signup.
600+
sendExistingAccountEmail(email);
598601
clearCaptcha();
599602
signupForm.setNewSignUp(false);
600603
return false;
@@ -727,6 +730,35 @@ private void createUserAndSendEmail(SignupForm form, ValidEmail email)
727730
}
728731
}
729732

733+
// Sends an informational email to the owner of an already-registered address when someone
734+
// submits the signup form for that address. Both the new-signup and existing-account paths
735+
// now send an email. The existing account is never modified. Send failures are logged and
736+
// swallowed so the caller still returns the same success response as a new signup.
737+
private void sendExistingAccountEmail(ValidEmail email)
738+
{
739+
Container c = getContainer();
740+
try
741+
{
742+
String siteName = LookAndFeelProperties.getInstance(c).getShortName();
743+
ActionURL loginUrl = PageFlowUtil.urlProvider(LoginUrls.class).getLoginURL(c, null);
744+
String body = "We received a request to create an account on " + siteName
745+
+ " using this email address. An account already exists for " + email.getEmailAddress() + ".\n\n"
746+
+ "If this was you and you have forgotten your password, go to the sign-in page and use "
747+
+ "the \"Forgot your password?\" link to reset it:\n" + loginUrl.getURIString() + "\n\n"
748+
+ "If you did not make this request, you can ignore this email.";
749+
MailHelper.ViewMessage m = MailHelper.createMessage(
750+
LookAndFeelProperties.getInstance(c).getSystemEmailAddress(), email.getEmailAddress());
751+
m.setSubject("You already have an account on " + siteName);
752+
m.setText(body);
753+
MailHelper.send(m, getUser(), c);
754+
}
755+
catch (Exception e)
756+
{
757+
// Log and continue so the response stays identical to the new-signup case.
758+
_log.error("Failed to send existing-account email", e);
759+
}
760+
}
761+
730762
private static List<String> errorsToMessages(Errors errors)
731763
{
732764
return errors.getAllErrors().stream()
@@ -954,9 +986,10 @@ public ApiResponse execute(SignupForm signupForm, BindException errors) throws E
954986
if (UserManager.userExists(email))
955987
{
956988
// Do not reveal whether an account already exists (avoids user enumeration).
957-
// Return the same response as a successful new signup, without sending an email.
989+
// Notify the account owner and return the same response as a successful new signup.
990+
sendExistingAccountEmail(email);
958991
clearCaptcha();
959-
response.put("status", "USER_ADDED");
992+
response.put("status", "SUCCESS");
960993
return response;
961994
}
962995

@@ -976,7 +1009,7 @@ public ApiResponse execute(SignupForm signupForm, BindException errors) throws E
9761009

9771010
clearCaptcha();
9781011

979-
response.put("status", "USER_ADDED");
1012+
response.put("status", "SUCCESS");
9801013
return response;
9811014
}
9821015
}

0 commit comments

Comments
 (0)