From: Felix Dörre Date: Mon, 17 Dec 2018 19:39:48 +0000 (+0100) Subject: Merge "fix: ensure no blanks are entered between name parts and hyphens" X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=bac148715f26957637ce90d78a5ebd783da866c5;hp=db4fbf8bd09c3b2f0286d1b65472b18d573a4227 Merge "fix: ensure no blanks are entered between name parts and hyphens" --- diff --git a/src/club/wpia/gigi/database/DatabaseConnection.java b/src/club/wpia/gigi/database/DatabaseConnection.java index 04351d1a..b5e78eaa 100644 --- a/src/club/wpia/gigi/database/DatabaseConnection.java +++ b/src/club/wpia/gigi/database/DatabaseConnection.java @@ -181,7 +181,7 @@ public class DatabaseConnection { } - public static final int CURRENT_SCHEMA_VERSION = 36; + public static final int CURRENT_SCHEMA_VERSION = 37; public static final int CONNECTION_TIMEOUT = 24 * 60 * 60; diff --git a/src/club/wpia/gigi/database/tableStructure.sql b/src/club/wpia/gigi/database/tableStructure.sql index 8c697f78..e9097fd1 100644 --- a/src/club/wpia/gigi/database/tableStructure.sql +++ b/src/club/wpia/gigi/database/tableStructure.sql @@ -163,6 +163,7 @@ CREATE TABLE "certs" ( "pkhash" char(40) DEFAULT NULL, "certhash" char(40) DEFAULT NULL, "description" varchar(100) NOT NULL DEFAULT '', + "actorid" int NOT NULL, PRIMARY KEY ("id") ); CREATE INDEX ON "certs" ("pkhash"); @@ -171,6 +172,7 @@ CREATE INDEX ON "certs" ("created"); CREATE INDEX ON "certs" ("memid"); CREATE INDEX ON "certs" ("serial"); CREATE INDEX ON "certs" ("expire"); +CREATE INDEX ON "certs" ("actorid"); DROP TABLE IF EXISTS "certAvas"; CREATE TABLE "certAvas" ( @@ -370,7 +372,7 @@ CREATE TABLE "schemeVersion" ( "version" smallint NOT NULL, PRIMARY KEY ("version") ); -INSERT INTO "schemeVersion" (version) VALUES(36); +INSERT INTO "schemeVersion" (version) VALUES(37); DROP TABLE IF EXISTS `passwordResetTickets`; CREATE TABLE `passwordResetTickets` ( diff --git a/src/club/wpia/gigi/database/upgrade/from_36.sql b/src/club/wpia/gigi/database/upgrade/from_36.sql new file mode 100644 index 00000000..1a33298e --- /dev/null +++ b/src/club/wpia/gigi/database/upgrade/from_36.sql @@ -0,0 +1,7 @@ +BEGIN; +ALTER TABLE "certs" ADD COLUMN "actorid" int; +CREATE INDEX ON "certs" ("actorid"); +UPDATE "certs" SET "actorid" = "memid" WHERE "profile" < 10; +UPDATE "certs" SET "actorid" = (SELECT "org_admin"."memid" FROM "org_admin" WHERE "org_admin"."orgid" = "certs"."memid" LIMIT 1) WHERE "profile" >= 10; +ALTER TABLE "certs" ALTER COLUMN "actorid" SET NOT NULL; +COMMIT; \ No newline at end of file diff --git a/src/club/wpia/gigi/dbObjects/Certificate.java b/src/club/wpia/gigi/dbObjects/Certificate.java index 28c32088..61fd7d34 100644 --- a/src/club/wpia/gigi/dbObjects/Certificate.java +++ b/src/club/wpia/gigi/dbObjects/Certificate.java @@ -166,6 +166,8 @@ public class Certificate implements IdCachable { private String description = ""; + private User actor; + public static final TranslateCommand NOT_LOADED = new TranslateCommand("Certificate could not be loaded"); public static final TranslateCommand NOT_PARSED = new TranslateCommand("Certificate could not be parsed"); @@ -212,13 +214,15 @@ public class Certificate implements IdCachable { this.csrType = csrType; this.profile = profile; this.sans = Arrays.asList(sans); + this.actor = actor; synchronized (Certificate.class) { - try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, memid=?, profile=?")) { + try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, memid=?, profile=?, actorid=?")) { inserter.setString(1, md.toString().toLowerCase()); inserter.setString(2, this.csrType.toString()); inserter.setInt(3, owner.getId()); inserter.setInt(4, profile.getId()); + inserter.setInt(5, this.actor.getId()); inserter.execute(); id = inserter.lastInsertId(); } @@ -253,6 +257,7 @@ public class Certificate implements IdCachable { profile = CertificateProfile.getById(rs.getInt("profile")); this.serial = rs.getString("serial"); this.description = rs.getString("description"); + this.actor = User.getById(rs.getInt("actorid")); try (GigiPreparedStatement ps2 = new GigiPreparedStatement("SELECT `contents`, `type` FROM `subjectAlternativeNames` WHERE `certId`=?")) { ps2.setInt(1, id); @@ -417,7 +422,7 @@ public class Certificate implements IdCachable { if (serial == null) { return null; } - try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as `subject`, `md`,`memid`, `profile`, `certs`.`serial`, `certs`.`description` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as `subject`, `md`,`memid`, `profile`, `certs`.`serial`, `certs`.`description`, `certs`.`actorid` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) { ps.setString(1, serial.toString(16)); GigiResultSet rs = ps.executeQuery(); if ( !rs.next()) { @@ -443,7 +448,7 @@ public class Certificate implements IdCachable { } try { - try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, memid, profile, certs.serial, description FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=certs.id WHERE certs.id=? GROUP BY certs.id")) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, memid, profile, certs.serial, description, actorid FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=certs.id WHERE certs.id=? GROUP BY certs.id")) { ps.setInt(1, id); GigiResultSet rs = ps.executeQuery(); if ( !rs.next()) { @@ -495,6 +500,19 @@ public class Certificate implements IdCachable { return null; } + public java.util.Date getExpiryDate() { + if (getStatus() == CertificateStatus.ISSUED) { + try (GigiPreparedStatement prep = new GigiPreparedStatement("SELECT expire FROM certs WHERE id=?")) { + prep.setInt(1, getId()); + GigiResultSet res = prep.executeQuery(); + if (res.next()) { + return res.getTimestamp("expire"); + } + } + } + return null; + } + public void setLoginEnabled(boolean activate) { if (activate) { if ( !isLoginEnabled()) { @@ -589,6 +607,10 @@ public class Certificate implements IdCachable { return description; } + public User getActor() { + return actor; + } + public static Certificate locateCertificate(String serial, String certData) throws GigiApiException { if (serial != null && !serial.isEmpty()) { return getBySerial(normalizeSerial(serial)); diff --git a/src/club/wpia/gigi/dbObjects/EmailAddress.java b/src/club/wpia/gigi/dbObjects/EmailAddress.java index 7d4c984e..f8629d94 100644 --- a/src/club/wpia/gigi/dbObjects/EmailAddress.java +++ b/src/club/wpia/gigi/dbObjects/EmailAddress.java @@ -111,7 +111,7 @@ public class EmailAddress implements IdCachable, Verifyable { stmt.setInt(2, owner.getId()); stmt.setString(3, hash); if ( !stmt.executeMaybeUpdate()) { - throw new IllegalArgumentException("Given token could not be found to complete the verification process (Domain Ping)."); + throw new IllegalArgumentException("Given token could not be found to complete the verification process (Email Ping)."); } } // Verify user with that primary email diff --git a/src/club/wpia/gigi/dbObjects/Name.java b/src/club/wpia/gigi/dbObjects/Name.java index d5bff5cb..fbcf10ee 100644 --- a/src/club/wpia/gigi/dbObjects/Name.java +++ b/src/club/wpia/gigi/dbObjects/Name.java @@ -45,6 +45,11 @@ public class Name implements Outputable, IdCachable { */ public abstract void output(PrintWriter out); + /** + * @see Name#toInitialsString() + */ + public abstract String toInitialsString(); + } private static class SingleName extends SchemedName { @@ -70,6 +75,11 @@ public class Name implements Outputable, IdCachable { return singlePart.getValue(); } + @Override + public String toInitialsString() { + return singlePart.getValue().substring(0, 1); + } + @Override public NameSchemaType getSchemeName() { return NameSchemaType.SINGLE; @@ -223,6 +233,14 @@ public class Name implements Outputable, IdCachable { public String toAbbreviatedString() { return firstNames[0].getValue() + " " + lastNames[0].getValue().charAt(0) + "."; } + + @Override + public String toInitialsString() { + + String initals = getInitialByNamePart(firstNames, lastNames, suffixes); + + return initals; + } } private int id; @@ -378,8 +396,8 @@ public class Name implements Outputable, IdCachable { /** * Transforms this String into a short form. This short form should not be - * unique. (For "western" names this would be - * "firstName firstCharOfLastName.".) + * unique. (For "western" names this would be "firstName + * firstCharOfLastName.".) * * @return the short form of the name */ @@ -387,6 +405,17 @@ public class Name implements Outputable, IdCachable { return scheme.toAbbreviatedString(); } + /** + * Transforms this Name object into a short form. This short form might not + * be unique. (For "western" names this would be all first letters of each + * name part) + * + * @return the short form of the name + */ + public String toInitialsString() { + return scheme.toInitialsString(); + } + public int getVerificationPoints() { try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT SUM(`points`) FROM (SELECT DISTINCT ON (`from`, `method`) `points` FROM `notary` WHERE `to`=? AND `deleted` IS NULL AND (`expire` IS NULL OR `expire` > CURRENT_TIMESTAMP) ORDER BY `from`, `method`, `when` DESC) AS p")) { query.setInt(1, getId()); @@ -460,4 +489,27 @@ public class Name implements Outputable, IdCachable { } return owner; } + + private static String getInitialByNamePart(NamePart[]... npa) { + StringBuilder initals = new StringBuilder(); + for (NamePart[] np : npa) { + initals.append(getInitialByNamePart(np)); + } + return initals.toString(); + } + + private static String getInitialByNamePart(NamePart[] np) { + StringBuilder initals = new StringBuilder(); + for (NamePart p : np) { + switch (p.getValue()) { + case "-": + case "/": + break; + default: + initals.append(p.getValue().substring(0, 1).toUpperCase()); + break; + } + } + return initals.toString(); + } } diff --git a/src/club/wpia/gigi/dbObjects/User.java b/src/club/wpia/gigi/dbObjects/User.java index 9868e36a..1c6b39b3 100644 --- a/src/club/wpia/gigi/dbObjects/User.java +++ b/src/club/wpia/gigi/dbObjects/User.java @@ -23,7 +23,6 @@ import club.wpia.gigi.email.EmailProvider; import club.wpia.gigi.localisation.Language; import club.wpia.gigi.output.DateSelector; import club.wpia.gigi.pages.PasswordResetPage; -import club.wpia.gigi.passwords.PasswordStrengthChecker; import club.wpia.gigi.util.CalendarUtil; import club.wpia.gigi.util.DayDate; import club.wpia.gigi.util.Notary; @@ -454,6 +453,10 @@ public class User extends CertificateOwner { } + public synchronized String getInitials() { + return preferredName.toInitialsString(); + } + public boolean isInGroup(Group g) { return groups.contains(g); } diff --git a/src/club/wpia/gigi/output/CertificateIterable.java b/src/club/wpia/gigi/output/CertificateIterable.java index 0932dfa2..4ff458e9 100644 --- a/src/club/wpia/gigi/output/CertificateIterable.java +++ b/src/club/wpia/gigi/output/CertificateIterable.java @@ -46,6 +46,13 @@ public class CertificateIterable implements IterableDataset { vars.put("classIssued", ""); vars.put("classExpired", ""); vars.put("revoked", l.getTranslation("N/A")); + vars.put("actorinitials", l.getTranslation("N/A")); + vars.put("actorname", l.getTranslation("N/A")); + + if (c.getActor() != null) { + vars.put("actorinitials", c.getActor().getInitials()); + vars.put("actorname", c.getActor().getPreferredName().toString() + " <" + c.getActor().getEmail() + ">"); + } try { if (st == CertificateStatus.ISSUED || st == CertificateStatus.REVOKED) { diff --git a/src/club/wpia/gigi/output/CertificateTable.templ b/src/club/wpia/gigi/output/CertificateTable.templ index edf01ebc..30025248 100644 --- a/src/club/wpia/gigi/output/CertificateTable.templ +++ b/src/club/wpia/gigi/output/CertificateTable.templ @@ -11,6 +11,7 @@ + @@ -28,6 +29,7 @@ + diff --git a/src/club/wpia/gigi/output/NameInput.java b/src/club/wpia/gigi/output/NameInput.java index 51664667..272c06e4 100644 --- a/src/club/wpia/gigi/output/NameInput.java +++ b/src/club/wpia/gigi/output/NameInput.java @@ -74,8 +74,11 @@ public class NameInput implements Outputable { public NamePart[] getNameParts() throws GigiApiException { if ("single".equals(scheme)) { + if (name == null || name.trim().isEmpty()) { + throw new GigiApiException("requires at least one character in the single name"); + } return new NamePart[] { - new NamePart(NamePartType.SINGLE_NAME, name) + new NamePart(NamePartType.SINGLE_NAME, name.trim()) }; } String[] fparts = split(fname); diff --git a/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.java b/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.java index 95fce624..eebf2207 100644 --- a/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.java +++ b/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.java @@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletRequest; import club.wpia.gigi.GigiApiException; import club.wpia.gigi.dbObjects.CertificateOwner; import club.wpia.gigi.dbObjects.Domain; +import club.wpia.gigi.dbObjects.Organisation; import club.wpia.gigi.localisation.Language; import club.wpia.gigi.output.template.Form; import club.wpia.gigi.output.template.IterableDataset; @@ -22,10 +23,13 @@ public class DomainManagementForm extends Form { private boolean foreign; + private boolean readOnly; + public DomainManagementForm(HttpServletRequest hsr, CertificateOwner target, boolean foreign) { super(hsr); this.target = target; this.foreign = foreign; + readOnly = (target instanceof Organisation && !foreign); } @Override @@ -35,6 +39,9 @@ public class DomainManagementForm extends Form { int delId = Integer.parseInt(dels); Domain d = Domain.getById(delId); if (d != null && d.getOwner() == target) { + if (readOnly) { + throw new GigiApiException("You are not allowed to delete a domain."); + } d.delete(); } else { throw new GigiApiException("Domain was not found."); @@ -70,6 +77,12 @@ public class DomainManagementForm extends Form { } }; vars.put("domains", dts); + if (readOnly) { + vars.put("buttonvisible", null); + } else { + vars.put("buttonvisible", "buttonvisible"); + } + t.output(out, l, vars); } } diff --git a/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.templ b/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.templ index c003a48a..d022c271 100644 --- a/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.templ +++ b/src/club/wpia/gigi/pages/account/domain/DomainManagementForm.templ @@ -10,7 +10,7 @@ - + diff --git a/src/club/wpia/gigi/pages/main/CertStatusRequestForm.java b/src/club/wpia/gigi/pages/main/CertStatusRequestForm.java index 88e1264b..dd863176 100644 --- a/src/club/wpia/gigi/pages/main/CertStatusRequestForm.java +++ b/src/club/wpia/gigi/pages/main/CertStatusRequestForm.java @@ -1,6 +1,7 @@ package club.wpia.gigi.pages.main; import java.io.PrintWriter; +import java.util.Date; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -49,6 +50,9 @@ public class CertStatusRequestForm extends Form { java.util.Date revocationDate = c.getRevocationDate(); throw new PermamentFormException(new GigiApiException(SprintfCommand.createSimple("Certificate has been revoked on {0}.", revocationDate))); } + if (c.getExpiryDate().before(new Date())) { + return new SuccessMessageResult((SprintfCommand.createSimple("Certificate is valid but has expired on {0}.", c.getExpiryDate()))); + } return new SuccessMessageResult(new TranslateCommand("Certificate is valid.")); } diff --git a/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ b/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ index 5c63f04f..6978a60f 100644 --- a/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ +++ b/src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ @@ -1,4 +1,5 @@

+ diff --git a/src/club/wpia/gigi/pages/orga/ViewOrgPage.java b/src/club/wpia/gigi/pages/orga/ViewOrgPage.java index 909f9efe..6d7e9a2a 100644 --- a/src/club/wpia/gigi/pages/orga/ViewOrgPage.java +++ b/src/club/wpia/gigi/pages/orga/ViewOrgPage.java @@ -93,7 +93,7 @@ public class ViewOrgPage extends ManagedMultiFormPage { return; } Map vars = Page.getDefaultVars(req); - if (orgAss) { + if (orgAss && !myOrgs.contains(o)) { vars.put("editForm", new CreateOrgForm(req, o)); vars.put("affForm", new AffiliationForm(req, o)); vars.put("mgmDom", new DomainManagementForm(req, o, true)); diff --git a/src/club/wpia/gigi/util/TimeConditions.java b/src/club/wpia/gigi/util/TimeConditions.java index 33968814..bd6751fb 100644 --- a/src/club/wpia/gigi/util/TimeConditions.java +++ b/src/club/wpia/gigi/util/TimeConditions.java @@ -21,7 +21,7 @@ public class TimeConditions { private TimeConditions(Properties ppts) { testValidMonths = Integer.parseInt(ppts.getProperty("time.testValidMonths", "12")); reverificationDays = Integer.parseInt(ppts.getProperty("time.reverificationDays", "90")); - verificationFreshMonths = Integer.parseInt(ppts.getProperty("time.verificationFreshMonths", "39")); + verificationFreshMonths = Integer.parseInt(ppts.getProperty("time.verificationFreshMonths", "27")); verificationMaxAgeMonths = Integer.parseInt(ppts.getProperty("time.verificationMaxAgeMonths", "24")); emailPingMonths = Integer.parseInt(ppts.getProperty("time.emailPingMonths", "6")); } diff --git a/tests/club/wpia/gigi/dbObjects/TestCertificate.java b/tests/club/wpia/gigi/dbObjects/TestCertificate.java index fe35729a..0b4d6549 100644 --- a/tests/club/wpia/gigi/dbObjects/TestCertificate.java +++ b/tests/club/wpia/gigi/dbObjects/TestCertificate.java @@ -67,4 +67,14 @@ public class TestCertificate extends ClientBusinessTest { assertEquals(key, c.getAttachment(AttachmentType.CSR)); assertEquals("b", c.getAttachment(AttachmentType.CRT)); } + + @Test + public void testActor() throws GeneralSecurityException, IOException, GigiApiException { + KeyPair kp = generateKeypair(); + String key = generatePEMCSR(kp, "CN=testmail@example.com"); + Certificate c = new Certificate(u, u, Certificate.buildDN("CN", "testmail@example.com"), Digest.SHA256, key, CSRType.CSR, getClientProfile()); + + assertEquals(u, c.getActor()); + assertEquals("AB", c.getActor().getInitials()); + } } diff --git a/tests/club/wpia/gigi/dbObjects/TestUser.java b/tests/club/wpia/gigi/dbObjects/TestUser.java new file mode 100644 index 00000000..b25970b6 --- /dev/null +++ b/tests/club/wpia/gigi/dbObjects/TestUser.java @@ -0,0 +1,67 @@ +package club.wpia.gigi.dbObjects; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.dbObjects.NamePart.NamePartType; +import club.wpia.gigi.testUtils.ClientBusinessTest; + +public class TestUser extends ClientBusinessTest { + + @Test + public void testGetInitials() throws GigiApiException { + User u0 = User.getById(createVerificationUser("Kurti", "Hansel", createUniqueName() + "@email.com", TEST_PASSWORD)); + + assertEquals("KH", u0.getInitials()); + + // single name as preferred name + Name sName = new Name(u0, new NamePart(NamePartType.SINGLE_NAME, "SingleName")); + u0.setPreferredName(sName); + assertEquals("S", u0.getInitials()); + + // second western style name as preferred name + NamePart[] np = { + new NamePart(NamePartType.FIRST_NAME, "John"), new NamePart(NamePartType.FIRST_NAME, "Walker"), new NamePart(NamePartType.LAST_NAME, "Hansel") + }; + sName = new Name(u0, np); + u0.setPreferredName(sName); + assertEquals("JWH", u0.getInitials()); + // second western style name as preferred name + + NamePart[] np1 = { + new NamePart(NamePartType.FIRST_NAME, "Dieter"), new NamePart(NamePartType.LAST_NAME, "Hansel"), new NamePart(NamePartType.LAST_NAME, "von"), new NamePart(NamePartType.LAST_NAME, "Hof"), new NamePart(NamePartType.SUFFIX, "Meister") + }; + sName = new Name(u0, np1); + u0.setPreferredName(sName); + assertEquals("DHVHM", u0.getInitials()); + + // western style name with dash as preferred name (Hans-Peter) + NamePart[] np2 = { + new NamePart(NamePartType.FIRST_NAME, "Hans-Peter"), new NamePart(NamePartType.LAST_NAME, "Hansel") + }; + sName = new Name(u0, np2); + u0.setPreferredName(sName); + assertEquals("HH", u0.getInitials()); + + // western style name with dash as separate entry as preferred name + // (Hans - Peter) + NamePart[] np3 = { + new NamePart(NamePartType.FIRST_NAME, "Hans"), new NamePart(NamePartType.FIRST_NAME, "-"), new NamePart(NamePartType.FIRST_NAME, "Joachim"), new NamePart(NamePartType.LAST_NAME, "Hansel") + }; + sName = new Name(u0, np3); + u0.setPreferredName(sName); + assertEquals("HJH", u0.getInitials()); + + // western style name with / as separate entry as preferred name + // (Hans / Peter) + NamePart[] np4 = { + new NamePart(NamePartType.FIRST_NAME, "Hans"), new NamePart(NamePartType.FIRST_NAME, "/"), new NamePart(NamePartType.FIRST_NAME, "Peter"), new NamePart(NamePartType.LAST_NAME, "Hansel") + }; + sName = new Name(u0, np4); + u0.setPreferredName(sName); + assertEquals("HPH", u0.getInitials()); + } + +} diff --git a/tests/club/wpia/gigi/dbObjects/TestVerification.java b/tests/club/wpia/gigi/dbObjects/TestVerification.java index a20f4cef..2cb26ca8 100644 --- a/tests/club/wpia/gigi/dbObjects/TestVerification.java +++ b/tests/club/wpia/gigi/dbObjects/TestVerification.java @@ -10,7 +10,6 @@ import org.junit.Test; import club.wpia.gigi.GigiApiException; import club.wpia.gigi.database.GigiPreparedStatement; -import club.wpia.gigi.dbObjects.User; import club.wpia.gigi.testUtils.BusinessTest; import club.wpia.gigi.util.DayDate; import club.wpia.gigi.util.Notary; @@ -22,13 +21,13 @@ public class TestVerification extends BusinessTest { private final Timestamp tomorrow = new Timestamp(System.currentTimeMillis() + DayDate.MILLI_DAY); /** - * at least 39 months ago, so is outside the window of + * at least 27 months ago, so is outside the window of * {@link User#VERIFICATION_MONTHS} */ - private final Timestamp min39month = new Timestamp(System.currentTimeMillis() - DayDate.MILLI_DAY * 39 * 31); + private final Timestamp min27month = new Timestamp(System.currentTimeMillis() - DayDate.MILLI_DAY * 27 * 31); /** - * at least 24 months ago (but less than 39), so is inside the window of + * at least 24 months ago (but less than 27), so is inside the window of * {@link User#VERIFICATION_MONTHS} */ private final Timestamp min24month = new Timestamp(System.currentTimeMillis() - DayDate.MILLI_DAY * 24 * 31); @@ -134,7 +133,7 @@ public class TestVerification extends BusinessTest { @Test public void testApprox39MonthAgo() throws IOException { - enterVerificationWhen(agentID, applicantNameID, min39month); + enterVerificationWhen(agentID, applicantNameID, min27month); assertFalse(applicant.isInVerificationLimit()); } @@ -167,7 +166,7 @@ public class TestVerification extends BusinessTest { User agent = User.getById(agentID); User applicantMult = User.getById(applicantMultID); - enterVerificationWhen(agentID, applicantMult.getPreferredName().getId(), min39month); + enterVerificationWhen(agentID, applicantMult.getPreferredName().getId(), min27month); // test that new entry would be possible assertTrue(Notary.checkVerificationIsPossible(agent, applicantMult.getPreferredName())); @@ -186,7 +185,7 @@ public class TestVerification extends BusinessTest { User agent = User.getById(agentID); User applicantMult = User.getById(applicantMultID); - enterVerificationWhen(agentID, applicantMult.getPreferredName().getId(), min39month); + enterVerificationWhen(agentID, applicantMult.getPreferredName().getId(), min27month); int xPoints = agent.getExperiencePoints(); // test that VP after first entry diff --git a/tests/club/wpia/gigi/pages/main/CertStatusTest.java b/tests/club/wpia/gigi/pages/main/CertStatusTest.java index 373c55c2..f16ebb36 100644 --- a/tests/club/wpia/gigi/pages/main/CertStatusTest.java +++ b/tests/club/wpia/gigi/pages/main/CertStatusTest.java @@ -11,11 +11,14 @@ import java.net.URLConnection; import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.KeyPair; +import java.time.LocalDate; +import java.time.ZoneId; import org.hamcrest.CoreMatchers; import org.junit.Test; import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.database.GigiPreparedStatement; import club.wpia.gigi.dbObjects.Certificate; import club.wpia.gigi.dbObjects.Certificate.CertificateStatus; import club.wpia.gigi.dbObjects.Certificate.RevocationType; @@ -31,8 +34,12 @@ public class CertStatusTest extends ClientTest { private Certificate cert; + private Certificate certExpired; + private String serial; + private String serialExpired; + private String foreignPEM = "-----BEGIN CERTIFICATE-----\n" + "MIIGvjCCBKagAwIBAgIVEQAAAAfLkxaJ4wATnrSBUbEr3UsxMA0GCSqGSIb3DQEB\n" + "DQUAMHExFzAVBgNVBAMMDkFzc3VyZWQgMjAxNy0yMSowKAYDVQQKDCFUZXN0IEVu\n" + "dmlyb25tZW50IENBIEx0ZC4tMTctMDMtMDQxHTAbBgNVBAsMFFRlc3QgRW52aXJv\n" + "bm1lbnQgQ0FzMQswCQYDVQQGEwJBVTAeFw0xNzA4MTUxMDI5NTdaFw0xNzA4MTYw\n" + "MDAwMDBaMDkxETAPBgNVBAMMCE1hcmN1cyBNMSQwIgYJKoZIhvcNAQkBFhVtLm1h\n" + "ZW5nZWxAaW5vcGlhZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" + "AQCv9hFCn69zHNapLimr4B9xK2PcYYRmINbBiihJ42WSIcf6VfxgQRPXZ9JCGDKn\n" + "haANqAyfOCuvtIuN1jJoYOo1VTQd3tkL9IvAwPVpsPiiHeYKqJRNxCkfU6kPGY2x\n" + "QV4+gDErXp/0AL792oAq6W3RoYIeiHXLKvLoYLBbSqtTCkfCYgEhv/3bflswU1JH\n" + "fr6QsvUJ1epH7QpiE5J8pp9hWKfcEufekYnMWASKITS4ronQcyfMocf9BlEf87ou\n" + "wri0NF8EBBhwq6C2+Ag9QlNHtylyUTj4+3XR//3K+6T/8neNK/9CNZ6sXqz5SnFX\n" + "BZTQONK2vavDvbSDhgQ0CuCbyN+rwjjSHYSgywqjkKb1tzB39N7Hd2fR5LcnBD3/\n" + "alQGIh808iukSm7TNwmdSCl2dRug2nTH5qdFLgk2wH+UcoOZH1lEn3UA2IYScmUH\n" + "sgeF6bIojS8Qj1UQZPwlblDiNvudYx2QQG9aNqWz+4O+6a5IpRugY9jnG5Z5sPum\n" + "IpXl1q+VNz8FLlZavpxccjGlIW0179kctA5FEoTHgogzE/rAt5tmHD+kdVEgpquR\n" + "yjpVVYG/R64oUQDjBeen1aKt2yzv+CP1frvml/bUKcb4qZ3z15K6gD0wrKQVWJoD\n" + "0j6gPAs10N2khPbjX9sYJqFr4Tket1DtCIusPQj7JxQm1wIDAQABo4IBgzCCAX8w\n" + "DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU5N/6GJVVMyrAd/HgiN7PQQ7mTOUwHwYD\n" + "VR0jBBgwFoAUwygt1+5B0HactieygKVNyE3m9W0wDgYDVR0PAQH/BAQDAgOoMB0G\n" + "A1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDCBjgYIKwYBBQUHAQEEgYEwfzAz\n" + "BggrBgEFBQcwAYYnaHR0cDovL2cyLm9jc3AudGVzdDEuYmFja3VwLmRvZ2NyYWZ0\n" + "LmRlMEgGCCsGAQUFBzAChjxodHRwOi8vZzIuY3J0LnRlc3QxLmJhY2t1cC5kb2dj\n" + "cmFmdC5kZS9nMi8yMDE3L2Fzc3VyZWQtMi5jcnQwTQYDVR0fBEYwRDBCoECgPoY8\n" + "aHR0cDovL2cyLmNybC50ZXN0MS5iYWNrdXAuZG9nY3JhZnQuZGUvZzIvMjAxNy9h\n" + "c3N1cmVkLTIuY3JsMCAGA1UdEQQZMBeBFW0ubWFlbmdlbEBpbm9waWFlLmNvbTAN\n" + "BgkqhkiG9w0BAQ0FAAOCAgEATRC7wwfFNExFk6LGcAbYSJViVs8ZgFuaTEzlBrik\n" + "mf9f8QA7Aj2bH2hqCdjbem1ElXhbADcJopS46P7yfH57zUj3qvD9znK0DdqWpvsO\n" + "nCB7/kdA0KysxTZ+D5gFgk/MpDfNP8ALB1SHGEOv/l4gQs0Zn6ORxt+4zrLzqExO\n" + "dMYdxcVQCl0ft5tQRUSxg1k2y8crgplR02TvhJCrb+RNCS0SQMkEA11bZKEpLBYk\n" + "bJMJYMr+SMN/wtC/vjXm9hrPGqnfqpJC7IqHUfzcBt10dGPqzvO/6xnEZn4YSgjr\n" + "MyoVUnOmcgolFrToYbXr3CNoQFO5Dgz7hbXH59/6ph35g7Q3hllTV+DGV753Baaa\n" + "bMgAsUeJqdMcJSAorLKjibinF/odbJ/kghAg7LBLQUmCvfYWzKhnfETXQ/qXbOk7\n" + "fufEB0z1AnzOB032Cde+FZg1NofjyF8N0UuK4l8fS+hSX6bcJaIuvUSNm5Mj2laZ\n" + "cskPgOu2Gng1JteLbotEKnruKshfKgo64Fq/mPASHfrSdAeQ/shlL6JG3QQeiw9k\n" + "Yu7lu7neRduthxwEdZ8EYrQ0fnHWrmnGsDCpvNIv1coaPc0ghi2pfGjEBAXGQoQ3\n" + "7Bia1anze/wG/9viZyuH1Ms10Ya9E8bPfB1D7B26tB6IZUNLaMnoYbCd+EN7Zjx/\n" + "Yac=\n" + "-----END CERTIFICATE-----"; public CertStatusTest() throws GeneralSecurityException, IOException, GigiApiException, InterruptedException { @@ -46,31 +53,44 @@ public class CertStatusTest extends ClientTest { await(j); serial = cert.getSerial().toLowerCase(); + certExpired = cr.draft(); + j = certExpired.issue(null, "2y", u); + await(j); + serialExpired = certExpired.getSerial().toLowerCase(); + try (GigiPreparedStatement prep = new GigiPreparedStatement("UPDATE `certs` SET `expire`=? WHERE `id`=?")) { + prep.setDate(1, java.sql.Date.valueOf(LocalDate.now(ZoneId.of("UTC")))); + prep.setInt(2, certExpired.getId()); + prep.execute(); + } + } @Test public void testCertStatus() throws IOException, InterruptedException, GigiApiException, GeneralSecurityException { - testExecution("serial=" + URLEncoder.encode(serial, "UTF-8"), null, false);// serial - testExecution("serial=0000" + URLEncoder.encode(serial, "UTF-8"), null, false);// leading - // Zeros - testExecution("serial=0000" + URLEncoder.encode(serial.toUpperCase(), "UTF-8"), null, false);// upper - // case + testExecution("serial=" + URLEncoder.encode(serial, "UTF-8"), null, false, false);// serial + testExecution("serial=0000" + URLEncoder.encode(serial, "UTF-8"), null, false, false);// leading + // Zeros + testExecution("serial=0000" + URLEncoder.encode(serial.toUpperCase(), "UTF-8"), null, false, false);// upper + // case - testExecution("serial=0000", "Malformed serial", false); - testExecution("serial=0lkd", "Malformed serial", false); + testExecution("serial=0000", "Malformed serial", false, false); + testExecution("serial=0lkd", "Malformed serial", false, false); - testExecution("cert=" + URLEncoder.encode(PEM.encode("CERTIFICATE", cert.cert().getEncoded()), "UTF-8"), null, false); - testExecution("cert=" + URLEncoder.encode(foreignPEM, "UTF-8"), "Certificate to check not found.", false); - testExecution("cert=sometext", "Certificate could not be parsed", false); + testExecution("cert=" + URLEncoder.encode(PEM.encode("CERTIFICATE", cert.cert().getEncoded()), "UTF-8"), null, false, false); + testExecution("cert=" + URLEncoder.encode(foreignPEM, "UTF-8"), "Certificate to check not found.", false, false); + testExecution("cert=sometext", "Certificate could not be parsed", false, false); await(cert.revoke(RevocationType.USER)); - testExecution("serial=" + URLEncoder.encode(serial, "UTF-8"), "Certificate has been revoked on ", true);// serial - testExecution("cert=" + URLEncoder.encode(PEM.encode("CERTIFICATE", cert.cert().getEncoded()), "UTF-8"), "Certificate has been revoked on ", true); + testExecution("serial=" + URLEncoder.encode(serial, "UTF-8"), "Certificate has been revoked on ", true, false);// serial + testExecution("cert=" + URLEncoder.encode(PEM.encode("CERTIFICATE", cert.cert().getEncoded()), "UTF-8"), "Certificate has been revoked on ", true, false); + + testExecution("serial=" + URLEncoder.encode(serialExpired, "UTF-8"), null, false, true);// serial + testExecution("cert=" + URLEncoder.encode(PEM.encode("CERTIFICATE", certExpired.cert().getEncoded()), "UTF-8"), null, false, true); } - public void testExecution(String query, String error, boolean revoked) throws IOException, InterruptedException, GigiApiException, GeneralSecurityException { + public void testExecution(String query, String error, boolean revoked, boolean expired) throws IOException, InterruptedException, GigiApiException, GeneralSecurityException { URLConnection uc = new URL("https://" + getServerName() + CertStatusRequestPage.PATH).openConnection(); uc.addRequestProperty("Cookie", cookie); String content = IOUtils.readURL(uc); @@ -88,7 +108,11 @@ public class CertStatusTest extends ClientTest { if (error == null) { assertThat(result, hasNoError()); - assertThat(result, CoreMatchers.containsString("Certificate is valid.")); + if (expired) { + assertThat(result, CoreMatchers.containsString("Certificate is valid but has expired on")); + } else { + assertThat(result, CoreMatchers.containsString("Certificate is valid.")); + } } else { assertThat(fetchStartErrorMessage(result), CoreMatchers.containsString(error)); if (revoked == false) { diff --git a/tests/club/wpia/gigi/pages/orga/TestOrgDomain.java b/tests/club/wpia/gigi/pages/orga/TestOrgDomain.java index c758b7c6..a17586b2 100644 --- a/tests/club/wpia/gigi/pages/orga/TestOrgDomain.java +++ b/tests/club/wpia/gigi/pages/orga/TestOrgDomain.java @@ -1,8 +1,10 @@ package club.wpia.gigi.pages.orga; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.io.IOException; +import java.net.URLConnection; import java.net.URLEncoder; import org.junit.Test; @@ -10,7 +12,9 @@ import org.junit.Test; import club.wpia.gigi.GigiApiException; import club.wpia.gigi.dbObjects.Domain; import club.wpia.gigi.dbObjects.Organisation; -import club.wpia.gigi.pages.orga.ViewOrgPage; +import club.wpia.gigi.dbObjects.User; +import club.wpia.gigi.pages.account.domain.DomainOverview; +import club.wpia.gigi.testUtils.IOUtils; import club.wpia.gigi.testUtils.OrgTest; public class TestOrgDomain extends OrgTest { @@ -87,4 +91,31 @@ public class TestOrgDomain extends OrgTest { assertEquals(0, o1.getDomains().length); assertEquals(0, u.getDomains().length); } + + @Test + public void testDelAsAdmin() throws IOException, GigiApiException { + Organisation o = createUniqueOrg(); + String dom = createUniqueName() + ".de"; + Domain d = new Domain(u, o, dom); + assertEquals(1, o.getDomains().length); + User admin = createOrgAdmin(o); + String adminCookie = login(admin.getEmail(), TEST_PASSWORD); + assertNull(executeBasicWebInteraction(adminCookie, SwitchOrganisation.PATH, "org:" + o.getId() + "=y", 0)); + + // test that delete button is not displayed + URLConnection uc = get(adminCookie, DomainOverview.PATH); + uc.setDoOutput(true); + String res = IOUtils.readURL(uc); + assertThat(res, not(containsString("Delete"))); + + // test that domain cannot be deleted by organisation administrator + assertNull(executeBasicWebInteraction(adminCookie, SwitchOrganisation.PATH, "org:" + o.getId() + "=y", 0)); + uc = post(adminCookie, DomainOverview.PATH, "delete=" + d.getId(), 0); + res = IOUtils.readURL(uc); + assertThat(res, containsString("You are not allowed to delete a domain.")); + + // verify that domain still belongs to organisation + assertEquals(1, o.getDomains().length); + + } } diff --git a/tests/club/wpia/gigi/testUtils/OrgTest.java b/tests/club/wpia/gigi/testUtils/OrgTest.java index 6a0c4d1c..2d79c5a4 100644 --- a/tests/club/wpia/gigi/testUtils/OrgTest.java +++ b/tests/club/wpia/gigi/testUtils/OrgTest.java @@ -4,9 +4,10 @@ import java.io.IOException; import club.wpia.gigi.GigiApiException; import club.wpia.gigi.dbObjects.Country; +import club.wpia.gigi.dbObjects.Country.CountryCodeType; import club.wpia.gigi.dbObjects.Group; import club.wpia.gigi.dbObjects.Organisation; -import club.wpia.gigi.dbObjects.Country.CountryCodeType; +import club.wpia.gigi.dbObjects.User; public class OrgTest extends ClientTest { @@ -21,4 +22,10 @@ public class OrgTest extends ClientTest { Organisation o1 = new Organisation(createUniqueName(), Country.getCountryByCode("DE", CountryCodeType.CODE_2_CHARS), "pr", "city", "test@example.com", "", "", u); return o1; } + + public User createOrgAdmin(Organisation o) throws GigiApiException { + User ua = User.getById(createVerificationUser("testworker", "testname", createUniqueName() + "@testdom.com", TEST_PASSWORD)); + o.addAdmin(ua, u, true); + return ua; + } }