]> WPIA git - gigi.git/commitdiff
Merge "fix: ensure no blanks are entered between name parts and hyphens"
authorFelix Dörre <felix@dogcraft.de>
Mon, 17 Dec 2018 19:39:48 +0000 (20:39 +0100)
committerGerrit Code Review <gigi-system@dogcraft.de>
Mon, 17 Dec 2018 19:39:48 +0000 (20:39 +0100)
22 files changed:
src/club/wpia/gigi/database/DatabaseConnection.java
src/club/wpia/gigi/database/tableStructure.sql
src/club/wpia/gigi/database/upgrade/from_36.sql [new file with mode: 0644]
src/club/wpia/gigi/dbObjects/Certificate.java
src/club/wpia/gigi/dbObjects/EmailAddress.java
src/club/wpia/gigi/dbObjects/Name.java
src/club/wpia/gigi/dbObjects/User.java
src/club/wpia/gigi/output/CertificateIterable.java
src/club/wpia/gigi/output/CertificateTable.templ
src/club/wpia/gigi/output/NameInput.java
src/club/wpia/gigi/pages/account/domain/DomainManagementForm.java
src/club/wpia/gigi/pages/account/domain/DomainManagementForm.templ
src/club/wpia/gigi/pages/main/CertStatusRequestForm.java
src/club/wpia/gigi/pages/orga/MyOrganisationsForm.templ
src/club/wpia/gigi/pages/orga/ViewOrgPage.java
src/club/wpia/gigi/util/TimeConditions.java
tests/club/wpia/gigi/dbObjects/TestCertificate.java
tests/club/wpia/gigi/dbObjects/TestUser.java [new file with mode: 0644]
tests/club/wpia/gigi/dbObjects/TestVerification.java
tests/club/wpia/gigi/pages/main/CertStatusTest.java
tests/club/wpia/gigi/pages/orga/TestOrgDomain.java
tests/club/wpia/gigi/testUtils/OrgTest.java

index 04351d1a38e8ab2af427c6f3c1473a5dfcac322a..b5e78eaaffa902764e0a29f938d3744848511b67 100644 (file)
@@ -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;
 
index 8c697f78a93376352554274e245d03e40adbe21d..e9097fd1a6eb0d22fc06b5b0cd19c2e040013a29 100644 (file)
@@ -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 (file)
index 0000000..1a33298
--- /dev/null
@@ -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
index 28c32088fd1f09e302f0327f2168f534215c9650..61fd7d341a11d0a07c4329a532d93a2eeb6c062f 100644 (file)
@@ -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));
index 7d4c984e8e8233892e537799ce8b3ec4b174e4d9..f8629d946bc85bc396947d2c360a2314704babde 100644 (file)
@@ -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
index d5bff5cbd8b52e9d5620dc065468afe574ed8ab0..fbcf10eed4c94fc76c8c975102e339e31c83f7a8 100644 (file)
@@ -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();
+    }
 }
index 9868e36a1d912efbeb6de98bc8d96537365fc6f0..1c6b39b377e7b67d31cbca4c6d9fd4633225e875 100644 (file)
@@ -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);
     }
index 0932dfa26dbdb601132da0dedaaa088a9f11d6a2..4ff458e9c8c993e410c2e6c0769a50abf705d711 100644 (file)
@@ -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) {
index edf01ebc0b4ed518558e64c4ccf53f1adddf8787..3002524896a18bb78ec207eff60ca4197469210f 100644 (file)
@@ -11,6 +11,7 @@
 <th><?=_Expires?></th>
 <th><?=_Login?></th>
 <th><?=_Description?></th>
+<th><?=_Issued by?></th>
 </tr></thead>
 <tbody>
 <? foreach($certs) {?>
@@ -28,6 +29,7 @@
        <td class="<?=$classExpired?>"><?=$expire?></td>
        <td><?=$login?></td>
        <td><?=$description?></td>
+       <td><span title="<?=$actorname?>"><?=$actorinitials?></span></td>
 </tr>
 <? } ?>
 </tbody>
index 516646674a55e9d947ae70601e0ecffdf519d2c2..272c06e4249a344a8ee63df3485b8ac9ba62a57c 100644 (file)
@@ -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);
index 95fce624c6bdd48c27a85fa134137308b5106978..eebf22073348c76d008543ea1e82aab0fb683ce8 100644 (file)
@@ -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);
     }
 }
index c003a48a07b4527cb10016fbb0d5d17aa782acd5..d022c27146501a08fa43c08358d163f5f56733b7 100644 (file)
@@ -10,7 +10,7 @@
   </tr>
   <? foreach($domains) { ?>
   <tr>
-       <td><button class="btn btn-danger btn-confirm" data-confirm="<?=_Do you really want to delete this domain??>" data-reply="<?=_Cancel?>,<?=_Confirm?>" type="submit" name="delete" value="<?=$id?>">Delete</button></td>
+       <td><? if($buttonvisible) { ?><button class="btn btn-danger btn-confirm" data-confirm="<?=_Do you really want to delete this domain??>" data-reply="<?=_Cancel?>,<?=_Confirm?>" type="submit" name="delete" value="<?=$id?>">Delete</button><? } ?></td>
        <td><?=$status?></td>
        <td><? if($domainhref) { ?><a href='<?=$domainhref?>'><?=$domain?><? } else { ?><?=$domain?><? } ?></a></td>
   </tr>
index 88e1264b7ed34cb2e0107e4726dc2f2d60abc6bc..dd863176f52cd6e3b97f82c7486110f4cc17fa2b 100644 (file)
@@ -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."));
     }
index 5c63f04fcc36e8ece29e533a5c974f0d39cfda0d..6978a60f98f2b02674ccd2855bed279355378249 100644 (file)
@@ -1,4 +1,5 @@
 <h2><?=_My Organisations?></h2>
+<input type="hidden" name="orgaForm" value="y">
 <? if($personal) { ?>
 <button class="btn btn-primary" type='submit' value='personal' name='org-leave'/><?=_Switch back to personal context?></button>
 <? } ?>
index 909f9efe62168bd22fe422e0d67a70b4c4dcefa3..6d7e9a2a034f28c0a59370e363bdb83142e61fa0 100644 (file)
@@ -93,7 +93,7 @@ public class ViewOrgPage extends ManagedMultiFormPage {
             return;
         }
         Map<String, Object> 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));
index 3396881450f7b2fcfaa1eabfa2502d8e17bc213b..bd6751fb935046c228ecfa926f0150a5fff7283b 100644 (file)
@@ -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"));
     }
index fe35729aed4a8e3c98c8455a5c7844977f39f618..0b4d6549d962ceb255ad924d3622a74ac6f3c021 100644 (file)
@@ -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 (file)
index 0000000..b25970b
--- /dev/null
@@ -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());
+    }
+
+}
index a20f4cefa75aa22f2659d4004e89f71368f13ffc..2cb26ca8dac0d014444961f6901b5ffa760e8f7e 100644 (file)
@@ -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
index 373c55c23df1d31d53e12d02d130c79208f8eaf4..f16ebb36af4c62115f0660f385a3448503c6c39d 100644 (file)
@@ -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) {
index c758b7c63701ad37c3965faf59a62383651490e7..a17586b27224c5f48c81ca113511782b18cf5036 100644 (file)
@@ -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);
+
+    }
 }
index 6a0c4d1c68cf70330b6ae4404656e6fe6e5d7b6f..2d79c5a497b0e15d289ff38e699599e8cabe414d 100644 (file)
@@ -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;
+    }
 }