From: Benny Baumann Date: Thu, 8 Feb 2018 19:48:29 +0000 (+0100) Subject: Merge "chg: extract url to links.txt" X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=be0c267ced95d9e08e179ad222439198b0176ac6;hp=3e8736567979048f5f9a8ff312178acfd1303566 Merge "chg: extract url to links.txt" --- diff --git a/src/club/wpia/gigi/Gigi.java b/src/club/wpia/gigi/Gigi.java index 6d8996c9..035f1a6f 100644 --- a/src/club/wpia/gigi/Gigi.java +++ b/src/club/wpia/gigi/Gigi.java @@ -71,6 +71,7 @@ import club.wpia.gigi.pages.main.CertStatusRequestPage; import club.wpia.gigi.pages.main.KeyCompromisePage; import club.wpia.gigi.pages.main.RegisterPage; import club.wpia.gigi.pages.orga.CreateOrgPage; +import club.wpia.gigi.pages.orga.SwitchOrganisation; import club.wpia.gigi.pages.orga.ViewOrgPage; import club.wpia.gigi.pages.statistics.StatisticsRoles; import club.wpia.gigi.pages.wot.Points; @@ -164,6 +165,7 @@ public final class Gigi extends HttpServlet { putPage(TTPAdminPage.PATH + "/*", new TTPAdminPage(), admMenu); putPage(CreateOrgPage.DEFAULT_PATH, new CreateOrgPage(), orgAdm); putPage(ViewOrgPage.DEFAULT_PATH + "/*", new ViewOrgPage(), orgAdm); + putPage(SwitchOrganisation.PATH, new SwitchOrganisation(), orgAdm); Menu support = createMenu("Support Console"); putPage(SupportEnterTicketPage.PATH, new SupportEnterTicketPage(), support); diff --git a/src/club/wpia/gigi/dbObjects/EmailAddress.java b/src/club/wpia/gigi/dbObjects/EmailAddress.java index 319e415b..7d4c984e 100644 --- a/src/club/wpia/gigi/dbObjects/EmailAddress.java +++ b/src/club/wpia/gigi/dbObjects/EmailAddress.java @@ -13,6 +13,7 @@ import club.wpia.gigi.email.MailProbe; import club.wpia.gigi.localisation.Language; import club.wpia.gigi.output.template.SprintfCommand; import club.wpia.gigi.util.RandomToken; +import club.wpia.gigi.util.TimeConditions; public class EmailAddress implements IdCachable, Verifyable { @@ -122,9 +123,10 @@ public class EmailAddress implements IdCachable, Verifyable { } public boolean isVerified() { - try (GigiPreparedStatement statmt = new GigiPreparedStatement("SELECT 1 FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active' AND `status`='success'")) { + try (GigiPreparedStatement statmt = new GigiPreparedStatement("SELECT 1 FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active' AND `status`='success' AND `when` > (now() - interval '1 months' * ?::INTEGER)")) { statmt.setString(1, address); statmt.setInt(2, owner.getId()); + statmt.setInt(3, TimeConditions.getInstance().getEmailPingMonths()); GigiResultSet e = statmt.executeQuery(); return e.next(); } diff --git a/src/club/wpia/gigi/pages/account/MyDetails.java b/src/club/wpia/gigi/pages/account/MyDetails.java index 12d127fa..b4a52d4e 100644 --- a/src/club/wpia/gigi/pages/account/MyDetails.java +++ b/src/club/wpia/gigi/pages/account/MyDetails.java @@ -10,6 +10,7 @@ import javax.servlet.http.HttpServletResponse; import club.wpia.gigi.output.template.Form; import club.wpia.gigi.pages.LoginPage; import club.wpia.gigi.pages.Page; +import club.wpia.gigi.pages.orga.MyOrganisationsForm; public class MyDetails extends Page { diff --git a/src/club/wpia/gigi/pages/account/MyOrganisationsForm.templ b/src/club/wpia/gigi/pages/account/MyOrganisationsForm.templ deleted file mode 100644 index 96d7bbe7..00000000 --- a/src/club/wpia/gigi/pages/account/MyOrganisationsForm.templ +++ /dev/null @@ -1,10 +0,0 @@ - -

- - - - -
- - - diff --git a/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java b/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java index 8a1bc594..cdf4dd41 100644 --- a/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java +++ b/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java @@ -35,6 +35,7 @@ import club.wpia.gigi.util.DomainAssessment; import club.wpia.gigi.util.PEM; import club.wpia.gigi.util.RateLimit; import club.wpia.gigi.util.ServerConstants; +import club.wpia.gigi.util.TimeConditions; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs10.PKCS10; import sun.security.pkcs10.PKCS10Attribute; @@ -356,8 +357,8 @@ public class CertificateRequest { valid = false; } } - } else if (san.getType() == SANType.EMAIL) { - if (emailTemp != null && owner.isValidEmail(san.getName())) { + } else if (san.getType() == SANType.EMAIL && emailTemp != null) { + if (owner.isValidEmail(san.getName())) { if (pMail != null && !emailTemp.isMultiple()) { // remove } else { @@ -367,6 +368,11 @@ public class CertificateRequest { filteredSANs.add(san); continue; } + } else { + // remove + error.mergeInto(new GigiApiException(SprintfCommand.createSimple(// + "The requested subject alternate name email address \"{0}\" needs an email ping within the past {1} months.", san.getType().toString().toLowerCase() + ":" + san.getName(), TimeConditions.getInstance().getEmailPingMonths()))); + break; } } error.mergeInto(new GigiApiException(SprintfCommand.createSimple(// diff --git a/src/club/wpia/gigi/pages/orga/AffiliationForm.java b/src/club/wpia/gigi/pages/orga/AffiliationForm.java index 278e38b7..1fd1c010 100644 --- a/src/club/wpia/gigi/pages/orga/AffiliationForm.java +++ b/src/club/wpia/gigi/pages/orga/AffiliationForm.java @@ -39,7 +39,7 @@ public class AffiliationForm extends Form { } else if (req.getParameter("do_affiliate") != null) { User byEmail = User.getByEmail(req.getParameter("email")); if (byEmail == null) { - throw new GigiApiException("To add an admin, the email address is required."); + throw new GigiApiException("To add an admin, the email address needs to be known to the system."); } if (byEmail.canVerify()) { o.addAdmin(byEmail, LoginPage.getUser(req), req.getParameter("master") != null); diff --git a/src/club/wpia/gigi/pages/account/MyOrganisationsForm.java b/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.java similarity index 94% rename from src/club/wpia/gigi/pages/account/MyOrganisationsForm.java rename to src/club/wpia/gigi/pages/orga/MyOrganisationsForm.java index 835973a1..8858c5c0 100644 --- a/src/club/wpia/gigi/pages/account/MyOrganisationsForm.java +++ b/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.java @@ -1,4 +1,4 @@ -package club.wpia.gigi.pages.account; +package club.wpia.gigi.pages.orga; import java.io.PrintWriter; import java.util.Enumeration; @@ -33,7 +33,7 @@ public class MyOrganisationsForm extends Form { public SubmissionResult submit(HttpServletRequest req) throws GigiApiException { if (req.getParameter("org-leave") != null) { req.getSession().setAttribute(Gigi.AUTH_CONTEXT, new AuthorizationContext(target.getActor(), target.getActor())); - return new RedirectResult(MyDetails.PATH); + return new RedirectResult(SwitchOrganisation.PATH); } Enumeration i = req.getParameterNames(); int orgId = -1; @@ -52,7 +52,7 @@ public class MyOrganisationsForm extends Form { if (org.getId() == orgId) { req.getSession().setAttribute(Gigi.AUTH_CONTEXT, new AuthorizationContext(org, target.getActor())); - return new RedirectResult(MyDetails.PATH); + return new RedirectResult(SwitchOrganisation.PATH); } } throw new PermamentFormException(new GigiApiException("Context switch failed.")); diff --git a/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ b/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ new file mode 100644 index 00000000..5c63f04f --- /dev/null +++ b/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ @@ -0,0 +1,9 @@ +

+ + + + + + + +
diff --git a/src/club/wpia/gigi/pages/orga/SwitchOrganisation.java b/src/club/wpia/gigi/pages/orga/SwitchOrganisation.java new file mode 100644 index 00000000..16dfe6ed --- /dev/null +++ b/src/club/wpia/gigi/pages/orga/SwitchOrganisation.java @@ -0,0 +1,29 @@ +package club.wpia.gigi.pages.orga; + +import java.io.IOException; +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import club.wpia.gigi.pages.ManagedFormPage; +import club.wpia.gigi.util.AuthorizationContext; + +public class SwitchOrganisation extends ManagedFormPage { + + public static final String PATH = "/orga/switch-orga"; + + public SwitchOrganisation() { + super("Switch to Organisation", MyOrganisationsForm.class); + } + + @Override + public boolean isPermitted(AuthorizationContext ac) { + return ac != null && ac.getActor().getOrganisations().size() != 0; + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + new MyOrganisationsForm(req).output(resp.getWriter(), getLanguage(req), new HashMap()); + } +} diff --git a/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java b/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java index 79edd932..da580ccf 100644 --- a/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java +++ b/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java @@ -6,14 +6,19 @@ import static org.junit.Assert.*; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyPair; +import java.util.Locale; import org.junit.Test; import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.database.GigiPreparedStatement; +import club.wpia.gigi.dbObjects.EmailAddress; import club.wpia.gigi.dbObjects.Group; import club.wpia.gigi.pages.account.certs.CertificateRequest; import club.wpia.gigi.testUtils.ClientTest; +import club.wpia.gigi.testUtils.TestEmailReceiver.TestMail; import club.wpia.gigi.util.AuthorizationContext; +import club.wpia.gigi.util.TimeConditions; public class TestCertificateRequest extends ClientTest { @@ -85,4 +90,50 @@ public class TestCertificateRequest extends ClientTest { } } + + @Test + public void testPingPeriodOneAddress() throws IOException, GeneralSecurityException, GigiApiException { + // get new email address with last ping in past + String furtherEmail = createUniqueName() + "@example.org"; + EmailAddress ea = new EmailAddress(u, furtherEmail, Locale.ENGLISH); + TestMail mail = getMailReceiver().receive(furtherEmail); + try (GigiPreparedStatement stmt = new GigiPreparedStatement("UPDATE `emailPinglog` SET `status`='success'::`pingState`, `when` = (now() - interval '1 months' * ?::INTEGER) WHERE `email`=? ")) { + stmt.setInt(1, TimeConditions.getInstance().getEmailPingMonths()); + stmt.setString(2, furtherEmail); + stmt.executeUpdate(); + } + + try { + CertificateRequest cr = new CertificateRequest(ac, generatePEMCSR(kp, "CN=a ab")); + cr.update("name", "SHA512", "mail", null, null, "email:" + furtherEmail); + cr.draft(); + fail(); + } catch (GigiApiException e) { + assertThat(e.getMessage(), containsString("needs an email ping within the past")); + } + + } + + @Test + public void testPingPeriodTwoAddresses() throws IOException, GeneralSecurityException, GigiApiException { + // get new email address with last ping in past + String furtherEmail = createUniqueName() + "@example.org"; + EmailAddress ea = new EmailAddress(u, furtherEmail, Locale.ENGLISH); + TestMail mail = getMailReceiver().receive(furtherEmail); + try (GigiPreparedStatement stmt = new GigiPreparedStatement("UPDATE `emailPinglog` SET `status`='success'::`pingState`, `when` = (now() - interval '1 months' * ?::INTEGER) WHERE `email`=? ")) { + stmt.setInt(1, TimeConditions.getInstance().getEmailPingMonths()); + stmt.setString(2, furtherEmail); + stmt.executeUpdate(); + } + + try { + CertificateRequest cr = new CertificateRequest(ac, generatePEMCSR(kp, "CN=a ab")); + cr.update("name", "SHA512", "mail", null, null, "email:" + furtherEmail + ",email:" + email); + cr.draft(); + fail(); + } catch (GigiApiException e) { + assertThat(e.getMessage(), containsString("needs an email ping within the past")); + } + + } } diff --git a/tests/club/wpia/gigi/pages/orga/TestOrgSwitch.java b/tests/club/wpia/gigi/pages/orga/TestOrgSwitch.java new file mode 100644 index 00000000..94586e34 --- /dev/null +++ b/tests/club/wpia/gigi/pages/orga/TestOrgSwitch.java @@ -0,0 +1,121 @@ +package club.wpia.gigi.pages.orga; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.URLEncoder; +import java.sql.SQLException; + +import org.junit.After; +import org.junit.Test; + +import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.dbObjects.Organisation; +import club.wpia.gigi.dbObjects.User; +import club.wpia.gigi.testUtils.IOUtils; +import club.wpia.gigi.testUtils.OrgTest; + +public class TestOrgSwitch extends OrgTest { + + private User u2; + + private Organisation org1 = createUniqueOrg(); + + private Organisation org2 = createUniqueOrg(); + + public TestOrgSwitch() throws IOException, GigiApiException { + + assertEquals(403, get(SwitchOrganisation.PATH).getResponseCode()); + + String email = createUniqueName() + "@testdom.com"; + u2 = User.getById(createVerificationUser("testworker", "testname", email, TEST_PASSWORD)); + assertNull(executeBasicWebInteraction(cookie, ViewOrgPage.DEFAULT_PATH + "/" + org1.getId(), "email=" + URLEncoder.encode(u2.getEmail(), "UTF-8") + "&do_affiliate=y&master=y", 1)); + assertNull(executeBasicWebInteraction(cookie, ViewOrgPage.DEFAULT_PATH + "/" + org2.getId(), "email=" + URLEncoder.encode(u2.getEmail(), "UTF-8") + "&do_affiliate=y&master=y", 1)); + + // login with new user u2 + cookie = login(email, TEST_PASSWORD); + } + + @After + public void purgeDbAfterTest() throws SQLException, IOException { + purgeDatabase(); + } + + @Test + public void testSwitchToOrg() throws IOException, GigiApiException { + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org1.getId() + "=y", 0)); + + String res = IOUtils.readURL(get(SwitchOrganisation.PATH)); + assertThat(res, containsString("Logged in as " + org1.getName() + " (on behalf of " + u2.getPreferredName())); + + } + + @Test + public void testSwitchToNonOrg() throws IOException, GigiApiException { + + String res = IOUtils.readURL(post(SwitchOrganisation.PATH, "org:5000=y")); + assertThat(res, containsString("Context switch failed")); + + } + + @Test + public void testSwitchToPersonal() throws IOException, GigiApiException { + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org-leave=personal", 0)); + + String res = IOUtils.readURL(get(SwitchOrganisation.PATH)); + assertThat(res, containsString("Logged in as " + u2.getPreferredName())); + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org-leave=personal", 0)); + + res = IOUtils.readURL(get(SwitchOrganisation.PATH)); + assertThat(res, containsString("Logged in as " + u2.getPreferredName())); + + } + + @Test + public void testSwitchOrgToOrg() throws IOException, GigiApiException { + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org1.getId() + "=y", 0)); + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org2.getId() + "=y", 0)); + + String res = IOUtils.readURL(get(SwitchOrganisation.PATH)); + assertThat(res, containsString("Logged in as " + org2.getName() + " (on behalf of " + u2.getPreferredName())); + + } + + @Test + public void testSwitchOrgToSameOrg() throws IOException, GigiApiException { + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org1.getId() + "=y", 0)); + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org1.getId() + "=y", 0)); + + String res = IOUtils.readURL(get(SwitchOrganisation.PATH)); + assertThat(res, containsString("Logged in as " + org1.getName() + " (on behalf of " + u2.getPreferredName())); + + } + + @Test + public void testSwitchOrgToNonOrg() throws IOException, GigiApiException { + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org1.getId() + "=y", 0)); + String res = IOUtils.readURL(post(SwitchOrganisation.PATH, "org:5000=y")); + assertThat(res, containsString("Context switch failed")); + + } + + @Test + public void testSwitchOrgToPersonal() throws IOException, GigiApiException { + + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org:" + org1.getId() + "=y", 0)); + assertNull(executeBasicWebInteraction(cookie, SwitchOrganisation.PATH, "org-leave=personal", 0)); + + String res = IOUtils.readURL(get(SwitchOrganisation.PATH)); + assertThat(res, containsString("Logged in as " + u2.getPreferredName())); + + } + +}