DataMigration, other Batch 52/79452/3
authorInstrumental <jonathan.gathman@att.com>
Fri, 1 Mar 2019 13:46:31 +0000 (07:46 -0600)
committerInstrumental <jonathan.gathman@att.com>
Fri, 1 Mar 2019 14:07:39 +0000 (08:07 -0600)
Issue-ID: AAF-776, AAF-753
Change-Id: Ia0593d7297c7af21c801b735f28ccab6867031f0
Signed-off-by: Instrumental <jonathan.gathman@att.com>
16 files changed:
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/helpers/CQLBatchLoop.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/helpers/X509.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/Notify.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/NsRoleUserReport.java [deleted file]
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/NotifyBody.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/NotifyCredBody.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/NotifyPendingApprBody.java [new file with mode: 0644]
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/NotifyURBody.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/OneMonthNotifyCredBody.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/OneMonthNotifyURBody.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/TwoWeeksNotifyCredBody.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/Approvals.java
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/NotifyApprovals.java [deleted file]
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/NotifyCredExpiring.java [deleted file]
auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/Remove.java
version.properties

index 51a88ef..945fe0b 100644 (file)
@@ -82,4 +82,10 @@ public class CQLBatchLoop {
        public int batches() {
                return batches;
        }
+
+       public void reset() {
+               count = 0;
+               batches = 0;
+               i = -1;
+       }
 }
index 39f017c..6a7ffc5 100644 (file)
@@ -125,7 +125,13 @@ public class X509 {
        sb.append(";\n");
        }
 
-
+    public static void batchDelete(StringBuilder sb, List<String> row) {
+       sb.append("DELETE from authz.x509 WHERE ca='");
+       sb.append(row.get(1));
+       sb.append("' AND serial=");
+       sb.append(row.get(2));
+       sb.append(";\n");
+       }
        public static String histSubject(List<String> row) {
                return row.get(4);
        }
index bf73c1d..0524c5c 100644 (file)
                                                                 if(identity==null) {
                                                                         trans.warn().printf("Responsible Identity %s is invalid for this Organization. Skipping notification.",id);
                                                                 } else {
-                                                                        for(int i=1;i<nb.escalation();++i) {
+                                                                        for(int i=1;i<=nb.escalation();++i) {
                                                                                 if(identity != null) {
                                                                                         if(i==1) {
                                                                                                 toList.add(identity.email());
+                                                                                                List<String> dels = identity.delegate();
+                                                                                                if(dels!=null) {
+                                                                                                        for(String d : dels) {
+                                                                                                                toList.add(d);
+                                                                                                        }
+                                                                                                }
                                                                                         } else {
-                                                                                                identity=identity.responsibleTo();
-                                                                                                ccList.add(identity.email());
+                                                                                                Identity s = identity.responsibleTo();
+                                                                                                if(s==null) {
+                                                                                                        trans.error().printf("Identity %s has no %s", identity.fullID(),
+                                                                                                                        identity.isPerson()?"supervisor":"sponsor");
+                                                                                                } else {
+                                                                                                        ccList.add(s.email());
+                                                                                                }
                                                                                         }
                                                                                 }
                                                                         }
                                                                         nb.body(noAvg, content, indent, notify, id);
                                                                         content.append(footer);
        
-                                                                        if(mailer.sendEmail(noAvg, test, toList, ccList, subject,content.toString(), urgent)) {
+                                                                        if(mailer.sendEmail(noAvg, test, toList, ccList, nb.subject(),content.toString(), urgent)) {
                                                                                 nb.inc();
                                                                         } else {
                                                                                 trans.error().log("Mailer failed to send Mail");
diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/NsRoleUserReport.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/NsRoleUserReport.java
deleted file mode 100644 (file)
index fcdc663..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * ============LICENSE_START====================================================
- * org.onap.aaf
- * ===========================================================================
- * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
- * ===========================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END====================================================
- *
- */
-
-package org.onap.aaf.auth.batch.reports;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-import org.onap.aaf.auth.batch.Batch;
-import org.onap.aaf.auth.batch.helpers.NS;
-import org.onap.aaf.auth.batch.helpers.Role;
-import org.onap.aaf.auth.batch.helpers.UserRole;
-import org.onap.aaf.auth.batch.helpers.Visitor;
-import org.onap.aaf.auth.env.AuthzTrans;
-import org.onap.aaf.auth.org.OrganizationException;
-import org.onap.aaf.cadi.util.CSV;
-import org.onap.aaf.cadi.util.CSV.Writer;
-import org.onap.aaf.misc.env.APIException;
-import org.onap.aaf.misc.env.Env;
-import org.onap.aaf.misc.env.TimeTaken;
-import org.onap.aaf.misc.env.util.Chrono;
-
-
-public class NsRoleUserReport extends Batch {
-    
-       private static final String REPORT = NsRoleUserReport.class.getSimpleName();
-       private static final String CSV = ".csv";
-       private Date now;
-       private Writer report;
-       private Map<String,Map<String,Integer>> theMap;
-       
-       public NsRoleUserReport(AuthzTrans trans) throws APIException, IOException, OrganizationException {
-        super(trans.env());
-        trans.info().log("Starting Connection Process");
-        
-        TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB);
-        try {
-            TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE);
-            try {
-                session = cluster.connect();
-            } finally {
-                tt.done();
-            }
-            
-            // Create Intermediate Output 
-            now = new Date();
-            String sdate = Chrono.dateOnlyStamp(now);
-               File file = new File(logDir(),REPORT + sdate +CSV);
-            CSV csv = new CSV(env.access(),file);
-            report = csv.writer(false);
-            
-            theMap = new TreeMap<>();
-
-            NS.load(trans, session, NS.v2_0_11);
-            Role.load(trans, session);
-        } finally {
-            tt0.done();
-        }
-    }
-
-    @Override
-    protected void run(AuthzTrans trans) {
-               try {
-                       trans.info().log("Create Report on Roles by NS");
-                       
-                       final AuthzTrans transNoAvg = trans.env().newTransNoAvg();
-                       UserRole.load(transNoAvg, session, UserRole.v2_0_11, ur -> {
-                               if(ur.expires().after(now)) {
-                                       Map<String, Integer> roleCount = theMap.get(ur.ns());
-                                       Integer count;
-                                       if(roleCount==null) {
-                                               roleCount = new TreeMap<>();
-                                               theMap.put(ur.ns(),roleCount);
-                                               count = 0;
-                                       } else {
-                                               count = roleCount.get(ur.rname());
-                                               if(count == null) {
-                                                       count = 0;
-                                               }
-                                       }
-                                       roleCount.put(ur.rname(), count+1);
-                               }
-                       });
-                       
-                       for(Entry<String, Map<String, Integer>> ns_es : theMap.entrySet()) {
-                               for(Entry<String, Integer> r_es : ns_es.getValue().entrySet()) {
-                                       report.row(ns_es.getKey(),r_es.getKey(),r_es.getValue());
-                               }
-                       }
-
-
-               } finally {
-               }
-       }
-       @Override
-    protected void _close(AuthzTrans trans) {
-        session.close();
-        report.close();
-    }
-
-}
index b36cf64..034286c 100644 (file)
@@ -39,6 +39,7 @@ import java.util.TreeMap;
 import org.onap.aaf.auth.batch.reports.Notify;
 import org.onap.aaf.auth.env.AuthzTrans;
 import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.config.Config;
 import org.onap.aaf.misc.env.APIException;
 
 public abstract class NotifyBody {
@@ -48,17 +49,19 @@ public abstract class NotifyBody {
        protected Map<String,List<List<String>>> rows;
        private final String name;
        private final String type;
+       protected final String env;
        private String date;
        private int escalation;
        private int count;
        
-       public NotifyBody(final String type, final String name) {
+       public NotifyBody(Access access, final String type, final String name) {
                rows = new TreeMap<>();
                this.name = name;
                this.type = type;
                date="";
                escalation = 1;
                count = 0;
+               env = access.getProperty(Config.AAF_ENV,"DEVL");
        }
        
        public void store(List<String> row) {
@@ -122,6 +125,8 @@ public abstract class NotifyBody {
         */
        protected abstract String user(List<String> row);
        
+       public abstract String subject();
+
        /**
         * Get Notify Body based on key of
         * type|name
index e06be05..deac3e4 100644 (file)
@@ -33,14 +33,14 @@ public abstract class NotifyCredBody extends NotifyBody {
 
        private final String explanation;
        public NotifyCredBody(Access access, String name) throws IOException {
-               super("cred",name);
+               super(access,"cred",name);
                
                // Default
                explanation = "The following Credentials are expiring on the dates shown. "
                                + "Failure to act before the expiration date will cause your App's "
                                + "Authentications to fail."
                                + "<h3>Instructions for 'Password':</h3><ul>" 
-                               + "<li>Click on the Fully Qualified ID to ADD a new Password</li>"
+                               + "<li><b><i>Click</i></b> on the Fully Qualified ID to ADD a new Password</li>"
                                + "<li><b>REMEMBER!</b> You are not finished until you <ol>"
                                + "<li><b>CHANGE <i>ALL</i></b> the configurations on <b><i>ALL</i></b> your processes!!</li>"
                                + "<li><b>BOUNCE</b> them</li></ol>"
diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/NotifyPendingApprBody.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/bodies/NotifyPendingApprBody.java
new file mode 100644 (file)
index 0000000..502464e
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.batch.reports.bodies;
+
+import java.util.List;
+
+import org.onap.aaf.auth.batch.reports.Notify;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.cadi.Access;
+
+public class NotifyPendingApprBody extends NotifyBody {
+       private final String explanation;
+
+       public NotifyPendingApprBody(Access access) {
+               super(access,"appr","PendingApproval");
+               explanation = "The following Approvals are awaiting your action. ";
+       }
+
+       @Override
+       public boolean body(AuthzTrans trans, StringBuilder sb, int indent, Notify n, String id) {
+               println(sb,indent,explanation);
+/*             println(sb,indent,"<table>");
+               indent+=2;
+               println(sb,indent,"<tr>");
+               indent+=2;
+               println(sb,indent,"<th>Fully Qualified ID</th>");
+               println(sb,indent,"<th>Unique ID</th>");
+               println(sb,indent,"<th>Type</th>");
+               println(sb,indent,"<th>Expires</th>");
+               println(sb,indent,"<th>Warnings</th>");
+               indent-=2;
+               println(sb,indent,"</tr>");
+               String theid, type, info, expires, warnings;
+               GregorianCalendar gc = new GregorianCalendar();
+               for(List<String> row : rows.get(id)) {
+                       theid=row.get(1);
+                       switch(row.get(3)) {
+                               case "1":
+                               case "2":
+                                       type = "Password";
+                                       break;
+                               case "200":
+                                       type = "x509 (Certificate)";
+                                       break;
+                               default:
+                                       type = "Unknown, see AAF GUI";
+                                       break;
+                       }
+                       theid = "<a href=\""+n.guiURL+"/creddetail?ns="+row.get(2)+"\">"+theid+"</a>";
+                       gc.setTimeInMillis(Long.parseLong(row.get(5)));
+                       expires = Chrono.niceUTCStamp(gc);
+                       info = row.get(6);
+                       //TODO get Warnings 
+                       warnings = "";
+                       
+                       println(sb,indent,"<tr>");
+                       indent+=2;
+                       printCell(sb,indent,theid);
+                       printCell(sb,indent,info);
+                       printCell(sb,indent,type);
+                       printCell(sb,indent,expires);
+                       printCell(sb,indent,warnings);
+                       indent-=2;
+                       println(sb,indent,"</tr>");
+               }
+               indent-=2;
+               println(sb,indent,"</table>");
+               */
+               return true;
+       }
+
+       @Override
+       public String user(List<String> row) {
+               if( (row != null) && row.size()>1) {
+                       return row.get(1);
+               }
+               return null;
+       }
+
+       @Override
+       public String subject() {
+               return String.format("AAF Pending Approval Notification (ENV: %s)",env);
+       }
+
+}
index e2c04d7..5e051e0 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.aaf.auth.batch.reports.bodies;
 
 import java.io.IOException;
+import java.util.Date;
 import java.util.List;
 
 import org.onap.aaf.auth.batch.reports.Notify;
@@ -28,17 +29,18 @@ import org.onap.aaf.auth.env.AuthzTrans;
 import org.onap.aaf.auth.org.Organization.Identity;
 import org.onap.aaf.auth.org.OrganizationException;
 import org.onap.aaf.cadi.Access;
+import org.onap.aaf.misc.env.util.Chrono;
 
 public abstract class NotifyURBody extends NotifyBody {
 
        private final String explanation;
        public NotifyURBody(Access access, String name) throws IOException {
-               super("ur",name);
+               super(access,"ur",name);
                
                // Default
                explanation = "The Roles for the IDs listed will expire on the dates shown. If "
-                               + "allowed to expire, the ID will no longer have access to the Permissions "
-                               + "associated with that Role.";
+                               + "allowed to expire, the ID will no longer authorized in that role.<br><br>"
+                               + "If the ID is for a current <b><i>Application</i></b>, this <b><i>WILL</i></b> cause an outage.";
        }
 
        @Override
@@ -63,6 +65,7 @@ public abstract class NotifyURBody extends NotifyBody {
                        fullname = "n/a";
                }
                println(sb,indent,explanation);
+               println(sb,indent,"<br><br>");
                println(sb,indent,"<table>");
                indent+=2;
                println(sb,indent,"<tr>");
@@ -82,7 +85,8 @@ public abstract class NotifyURBody extends NotifyBody {
                        name = printCell(sb,indent,fullname,name);
                        fqi = printCell(sb,indent,row.get(1),fqi);
                        printCell(sb,indent,row.get(2)+'.'+row.get(3));
-                       printCell(sb,indent,row.get(4));
+                       Date expires = new Date(Long.parseLong(row.get(6)));
+                       printCell(sb,indent,Chrono.niceUTCStamp(expires));
                        indent-=2;
                        println(sb,indent,"</tr>");
                }
index c3ed4f6..a288f49 100644 (file)
@@ -29,4 +29,9 @@ public class OneMonthNotifyCredBody extends NotifyCredBody {
        public OneMonthNotifyCredBody(Access access) throws IOException {
                super(access, ExpireRange.ONE_MONTH);
        }
+       
+       @Override
+       public String subject() {
+               return String.format("AAF One Month Credential Notification (ENV: %s)",env);
+       }
 }
index 8e4ea8b..5392c18 100644 (file)
@@ -29,4 +29,9 @@ public class OneMonthNotifyURBody extends NotifyURBody {
        public OneMonthNotifyURBody(Access access) throws IOException {
                super(access, ExpireRange.ONE_MONTH);
        }
+       
+       @Override
+       public String subject() {
+               return String.format("AAF One Month UserRole Notification (ENV: %s)",env);
+       }
 }
index e8a55c9..818556c 100644 (file)
@@ -29,4 +29,9 @@ public class TwoWeeksNotifyCredBody extends NotifyCredBody {
        public TwoWeeksNotifyCredBody(Access access) throws IOException {
                super(access, ExpireRange.TWO_WEEK);
        }
+
+       @Override
+       public String subject() {
+               return String.format("AAF Two Week Credential Notification (ENV: %s)",env);
+       }
 }
index 36fd627..2047098 100644 (file)
@@ -25,9 +25,11 @@ import java.io.File;
 import java.io.IOException;
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.TreeMap;
 
 import org.onap.aaf.auth.batch.Batch;
@@ -37,8 +39,10 @@ import org.onap.aaf.auth.batch.approvalsets.Pending;
 import org.onap.aaf.auth.batch.approvalsets.URApprovalSet;
 import org.onap.aaf.auth.batch.helpers.BatchDataView;
 import org.onap.aaf.auth.batch.helpers.NS;
+import org.onap.aaf.auth.batch.helpers.Notification;
 import org.onap.aaf.auth.batch.helpers.Role;
 import org.onap.aaf.auth.batch.helpers.UserRole;
+import org.onap.aaf.auth.batch.reports.bodies.NotifyPendingApprBody;
 import org.onap.aaf.auth.dao.cass.UserRoleDAO;
 import org.onap.aaf.auth.env.AuthzTrans;
 import org.onap.aaf.auth.layer.Result;
@@ -56,6 +60,7 @@ public class Approvals extends Batch {
        private BatchDataView dataview;
        private List<CSV> csvList;
        private GregorianCalendar now;
+       
 
     public Approvals(AuthzTrans trans) throws APIException, IOException, OrganizationException {
         super(trans.env());
@@ -90,7 +95,6 @@ public class Approvals extends Batch {
                        }
         }
         
-        
     }
 
     @Override
@@ -104,10 +108,11 @@ public class Approvals extends Batch {
                                        switch(row.get(0)) {
                                                case Pending.REMIND:
                                                        try {
+                                                               String user = row.get(1);
                                                                Pending p = new Pending(row);
-                                                               Pending mp = mpending.get(row.get(1));
+                                                               Pending mp = mpending.get(user);
                                                                if(mp==null) {
-                                                                       mpending.put(row.get(1), p);
+                                                                       mpending.put(user, p);
                                                                } else {
                                                                        mp.inc(p); // FYI, unlikely
                                                                }
@@ -165,9 +170,21 @@ public class Approvals extends Batch {
             trans.info().printf("Processed %d UserRoles", count.get());
 
             count.set(0);
+               NotifyPendingApprBody npab;
+               GregorianCalendar gc = new GregorianCalendar();
+               gc.add(GregorianCalendar.DAY_OF_MONTH, 7);
+               Date oneWeek = gc.getTime();
+               
+               Pending p;
                tt = trans.start("Notify for Pending", Trans.SUB);
                try {
-                       
+                       for(Entry<String, Pending> es : mpending.entrySet()) {
+                               p = es.getValue();
+                               Date earliest = p.earliest();
+                               if(p.newApprovals() || earliest==null || earliest.before(oneWeek) ) {
+                                       System.out.println("update");
+                               }
+                       }
                } finally {
                        tt.done();
                }
diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/NotifyApprovals.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/NotifyApprovals.java
deleted file mode 100644 (file)
index 7138a7c..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/**
- * ============LICENSE_START====================================================
- * org.onap.aaf
- * ===========================================================================
- * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
- *
- * Modifications Copyright (C) 2018 IBM.
- * ===========================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END====================================================
- *
- */
-
-package org.onap.aaf.auth.batch.update;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Map.Entry;
-
-import org.onap.aaf.auth.batch.Batch;
-import org.onap.aaf.auth.batch.BatchPrincipal;
-import org.onap.aaf.auth.batch.actions.Email;
-import org.onap.aaf.auth.batch.actions.EmailPrint;
-import org.onap.aaf.auth.batch.actions.Message;
-import org.onap.aaf.auth.batch.helpers.Approval;
-import org.onap.aaf.auth.batch.helpers.Future;
-import org.onap.aaf.auth.dao.CassAccess;
-import org.onap.aaf.auth.dao.cass.ApprovalDAO;
-import org.onap.aaf.auth.dao.cass.FutureDAO;
-import org.onap.aaf.auth.dao.cass.HistoryDAO;
-import org.onap.aaf.auth.env.AuthzTrans;
-import org.onap.aaf.auth.org.Organization;
-import org.onap.aaf.auth.org.Organization.Identity;
-import org.onap.aaf.auth.org.OrganizationException;
-import org.onap.aaf.auth.org.OrganizationFactory;
-import org.onap.aaf.cadi.Access;
-import org.onap.aaf.cadi.CadiException;
-import org.onap.aaf.cadi.config.RegistrationPropHolder;
-import org.onap.aaf.misc.env.APIException;
-import org.onap.aaf.misc.env.util.Chrono;
-
-public class NotifyApprovals extends Batch {
-    private static final String LINE = "----------------------------------------------------------------";
-    private final HistoryDAO historyDAO;
-    private final ApprovalDAO apprDAO;
-    private final FutureDAO futureDAO;
-    private Email email;
-    private int maxEmails;
-    private final PrintStream ps;
-    private final AuthzTrans noAvg;
-
-    public NotifyApprovals(AuthzTrans trans) throws APIException, IOException, OrganizationException, CadiException {
-        super(trans.env());
-        Access access = trans.env().access();
-        RegistrationPropHolder rph = new RegistrationPropHolder(access, 0);
-        String guiURL = rph.replacements(access.getProperty(GUI_URL,"https://%P/gui"),"","");
-        noAvg = env.newTransNoAvg();
-        noAvg.setUser(new BatchPrincipal("batch:NotifyApprovals"));
-
-        historyDAO = new HistoryDAO(trans, cluster, CassAccess.KEYSPACE);
-        session = historyDAO.getSession(trans);
-        apprDAO = new ApprovalDAO(trans, historyDAO);
-        futureDAO = new FutureDAO(trans, historyDAO);
-        if (isDryRun()) {
-            email = new EmailPrint();
-            maxEmails=3;
-        } else {
-            email = new Email();
-            maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
-        }
-        email.subject("AAF Approval Notification (ENV: %s)",batchEnv);
-        email.preamble("AAF is the ONAP Authorization System." +
-                "\n  Your approval is required, which you may enter on the following page:"
-                + "\n\n\t%s/approve\n\n"
-                ,guiURL);
-        email.signature("Sincerely,\nAAF Team\n");
-
-        Approval.load(trans, session, Approval.v2_0_17);
-        Future.load(trans, session, Future.v2_0_17); // Skip the Construct Data
-        
-        ps = new PrintStream(new FileOutputStream(logDir() + "/email"+Chrono.dateOnlyStamp()+".log",true));
-        ps.printf("### Approval Notify %s for %s%s\n",Chrono.dateTime(),batchEnv,dryRun?", DryRun":"");
-    }
-
-    @Override
-    protected void run(AuthzTrans trans) {
-        GregorianCalendar gc = new GregorianCalendar();
-        Date now = gc.getTime();
-        String today = Chrono.dateOnlyStamp(now);
-        gc.add(GregorianCalendar.MONTH, -1);
-        gc=null;
-
-
-        Message msg = new Message();
-        int emailCount = 0;
-        List<Approval> pending = new ArrayList<>();
-        boolean isOwner;
-        boolean isSupervisor;
-        for (Entry<String, List<Approval>> es : Approval.byApprover.entrySet()) {
-            isOwner = isSupervisor = false;
-            String approver = es.getKey();
-            if (approver.indexOf('@')<0) {
-                approver += org.getRealm();
-            }
-            Date latestNotify=null;
-            Date soonestExpire=null;
-            GregorianCalendar latest=new GregorianCalendar();
-            GregorianCalendar soonest=new GregorianCalendar();
-            pending.clear();
-            
-            for (Approval app : es.getValue()) {
-                Future f = app.getTicket()==null?null:Future.data.get(app.getTicket());
-                if (f==null) { // only Ticketed Approvals are valid.. the others are records.
-                    // Approvals without Tickets are no longer valid. 
-                    if ("pending".equals(app.getStatus())) {
-                        app.setStatus("lapsed");
-                        app.update(noAvg,apprDAO,dryRun); // obeys dryRun
-                    }
-                } else {
-                    if ((soonestExpire==null && f.expires()!=null) || (soonestExpire!=null && f.expires()!=null && soonestExpire.before(f.expires()))) {
-                        soonestExpire=f.expires();
-                    }
-
-                    if ("pending".equals(app.getStatus())) {
-                        if (!isOwner) {
-                            isOwner = "owner".equals(app.getType());
-                        }
-                        if (!isSupervisor) {
-                            isSupervisor = "supervisor".equals(app.getType());
-                        }
-
-                        if ((latestNotify==null && app.getLast_notified()!=null) ||(latestNotify!=null && app.getLast_notified()!=null && latestNotify.before(app.getLast_notified()))) {
-                            latestNotify=app.getLast_notified();
-                        }
-                        pending.add(app);
-                    }
-                }
-            }
-
-            if (!pending.isEmpty()) {
-                boolean go = false;
-                if (latestNotify==null) { // never notified... make it so
-                    go=true;
-                } else {
-                    if (!today.equals(Chrono.dateOnlyStamp(latest))) { // already notified today
-                        latest.setTime(latestNotify);
-                        soonest.setTime(soonestExpire);
-                        int year;
-                        int days = soonest.get(GregorianCalendar.DAY_OF_YEAR)-latest.get(GregorianCalendar.DAY_OF_YEAR);
-                        days+=((year=soonest.get(GregorianCalendar.YEAR))-latest.get(GregorianCalendar.YEAR))*365 + 
-                                (soonest.isLeapYear(year)?1:0);
-                        if (days<7) { // If Expirations get within a Week (or expired), notify everytime.
-                            go = true;
-                        }
-                    }
-                }
-                if (go && (maxEmails>emailCount++)) {
-                        try {
-                            Organization org = OrganizationFactory.obtain(env, approver);
-                            Identity user = org.getIdentity(noAvg, approver);
-                            if (user==null) {
-                                ps.printf("Invalid Identity: %s\n", approver);
-                            } else {
-                                email.clear();
-                                msg.clear();
-                                email.addTo(user.email());
-                                msg.line(LINE);
-                                msg.line("Why are you receiving this Notification?\n");
-                                if (isSupervisor) {
-                                    msg.line("%sYou are the supervisor of one or more employees who need access to tools which are protected by AAF.  " + 
-                                             "Your employees may ask for access to various tools and applications to do their jobs.  ASPR requires "
-                                             + "that you are notified and approve their requests. The details of each need is provided when you click "
-                                             + "on webpage above.\n",isOwner?"1) ":"");
-                                    msg.line("Your participation in this process fulfills the ASPR requirement to re-authorize users in roles on a regular basis.\n\n");
-                                }
-                            
-                                if (isOwner) {
-                                    msg.line("%sYou are the listed owner of one or more AAF Namespaces. ASPR requires that those responsible for "
-                                            + "applications and their access review them regularly for accuracy.  The AAF WIKI page for AT&T is https://wiki.web.att.com/display/aaf.  "
-                                            + "More info regarding questions of being a Namespace Owner is available at https://wiki.web.att.com/pages/viewpage.action?pageId=594741363\n",isSupervisor?"2) ":"");
-                                    msg.line("Additionally, Credentials attached to the Namespace must be renewed regularly.  While you may delegate certain functions to " + 
-                                             "Administrators within your Namespace, you are ultimately responsible to make sure credentials do not expire.\n");
-                                    msg.line("You may view the Namespaces you listed as Owner for in this AAF Env by viewing the following webpage:\n");
-                                    msg.line("   %s/ns\n\n",env.getProperty(GUI_URL));
-                                
-                                }
-                                msg.line("  If you are unfamiliar with AAF, you might like to peruse the following links:"
-                                        + "\n\thttps://wiki.web.att.com/display/aaf/AAF+in+a+Nutshell"
-                                        + "\n\thttps://wiki.web.att.com/display/aaf/The+New+Person%%27s+Guide+to+AAF");
-                                msg.line("\n  SPECIAL NOTE about SWM Management Groups: Understand that SWM management Groups correlate one-to-one to AAF Namespaces. "
-                                        + "(SWM uses AAF for the Authorization piece of Management Groups).  You may be assigned the SWM Management Group by asking "
-                                        + "directly, or through any of the above stated automated processes.  Auto-generated Namespaces typically look like 'com.att.44444.PROD' "
-                                        + "where '44444' is a MOTS ID, and 'PROD' is PROD|DEV|TEST, etc.  For your convenience, the MOTS link is http://ebiz.sbc.com/mots.\n");
-                                msg.line("  Finally, realize that there are automated processes which create Machines and Resources via SWM, Kubernetes or other "
-                                        + "such tooling.  If you or your predecessor requested them, you were set as the owner of the AAF Namespace created during "
-                                        + "that process.\n");
-                                msg.line("  For ALL QUESTIONS of why and how of SWM, and whether you or your reports can be removed, please contact SWM at "
-                                        + "https://wiki.web.att.com/display/swm/Support\n");
-
-                                email.msg(msg);
-                                email.exec(noAvg, org,"");
-                                if (!isDryRun()) {
-                                    email.log(ps,"NotifyApprovals");
-                                    for (Approval app : pending) {
-                                        app.setLastNotified(now);
-                                        app.update(noAvg, apprDAO, dryRun);
-                                    }
-                                }
-                            }
-                        } catch (OrganizationException e) {
-                            trans.info().log(e);
-                        }
-                }
-            }
-        }
-        trans.info().printf("%d emails sent for %s", emailCount,batchEnv);
-    }
-    
-    @Override
-    protected void _close(AuthzTrans trans) {
-        futureDAO.close(trans);
-        apprDAO.close(trans);
-        historyDAO.close(trans);
-        ps.close();
-    }
-}
diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/NotifyCredExpiring.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/update/NotifyCredExpiring.java
deleted file mode 100644 (file)
index ab563fe..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/**
- * ============LICENSE_START====================================================
- * org.onap.aaf
- * ===========================================================================
- * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
- *
- * Modifications Copyright (C) 2018 IBM.
- * ===========================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END====================================================
- *
- */
-
-package org.onap.aaf.auth.batch.update;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.onap.aaf.auth.batch.Batch;
-import org.onap.aaf.auth.batch.BatchPrincipal;
-import org.onap.aaf.auth.batch.actions.Email;
-import org.onap.aaf.auth.batch.actions.EmailPrint;
-import org.onap.aaf.auth.batch.helpers.Notification;
-import org.onap.aaf.auth.batch.helpers.UserRole;
-import org.onap.aaf.auth.env.AuthzTrans;
-import org.onap.aaf.auth.org.OrganizationException;
-import org.onap.aaf.cadi.CadiException;
-import org.onap.aaf.cadi.util.CSV;
-import org.onap.aaf.misc.env.APIException;
-import org.onap.aaf.misc.env.Env;
-import org.onap.aaf.misc.env.TimeTaken;
-import org.onap.aaf.misc.env.util.Chrono;
-
-
-public class NotifyCredExpiring extends Batch {
-
-    private static final String UNKNOWN_ID = "unknown@deprecated.id";
-    private static final String AAF_INSTANTIATED_MECHID = "AAF INSTANTIATED MECHID";
-    private static final String EXPIRATION_DATE = "EXPIRATION DATE";
-    private static final String QUICK_LINK = "QUICK LINK TO UPDATE PAGE";
-    private static final String DASH_1 = "-----------------------";
-    private static final String DASH_2 = "---------------";
-    private static final String DASH_3 = "----------------------------------------------------";
-    private static final String LINE = "\n----------------------------------------------------------------";
-    private Email email;
-    private int maxEmails;
-    private final PrintStream ps;
-    private final AuthzTrans noAvg;
-    private String supportEmailAddr;
-       private CSV csv;
-       private CSVInfo csvInfo;
-
-    public NotifyCredExpiring(AuthzTrans trans) throws APIException, IOException, OrganizationException, CadiException {
-        super(trans.env());
-        TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE);
-        try {
-            session = cluster.connect();
-        } finally {
-            tt.done();
-        }
-        
-        noAvg = env.newTransNoAvg();
-        noAvg.setUser(new BatchPrincipal("batch:NotifyCredExpiring"));
-        
-        if (isDryRun()) {
-            email = new EmailPrint();
-            maxEmails=3;
-            maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
-        } else {
-            email = new Email();
-            maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
-        }
-        
-        email.subject("AAF Password Expiration Notification (ENV: %s)",batchEnv);
-        email.preamble("AAF (MOTS 22830) is the AT&T Authorization System used by many AT&T Tools and Applications.\n\n" +
-                "  The following Credentials are expiring on the dates shown. Failure to act before the expiration date "
-                + "will cause your App's Authentications to fail.\n");
-        email.signature("Sincerely,\nAAF Team (Our MOTS# 22830)\n"
-                + "https://wiki.web.att.com/display/aaf/Contact+Us\n"
-                + "(Use 'Other Misc Requests (TOPS)')");
-        
-        boolean quit = false;
-        if(args().length<1) {
-               System.err.println("Need CSV formatted Expiring Report");
-               quit = true;
-        } else {
-               File f = new File(logDir(),args()[0]);
-               System.out.println("Reading " + f.getCanonicalPath());
-               csv = new CSV(env.access(),f);
-        }
-        
-        if(args().length<2) {
-               System.err.println("Need Email Template");
-               //quit = true;
-        }
-        if(quit) {
-               System.exit(2);
-        }
-        
-        csvInfo = new CSVInfo(System.err);
-               csv.visit(csvInfo);
-        
-        Notification.load(trans, session, Notification.v2_0_18);
-        
-        ps = new PrintStream(new FileOutputStream(logDir() + "/email"+Chrono.dateOnlyStamp()+".log",true));
-        ps.printf("### Approval Notify %s for %s%s\n",Chrono.dateTime(),batchEnv,dryRun?", DryRun":"");
-    }
-    
-    @Override
-    protected void run(AuthzTrans trans) {
-        
-        // Temp structures
-        Map<String,List<LastCred>> ownerCreds = new TreeMap<>();
-        
-
-        List<LastCred> noOwner = new ArrayList<>();
-        ownerCreds.put(UNKNOWN_ID,noOwner);
-        int emailCount=0;
-
-//        // Get a list of ONLY the ones needing email by Owner
-//        for (Entry<String, List<Cred>> es : Cred.byNS.entrySet()) {
-//            for (Cred c : es.getValue()) {
-//                List<UserRole> ownerURList = UserRole.getByRole().get(es.getKey()+".owner");
-//                if (ownerURList!=null) {
-//                    for (UserRole ur:ownerURList) {
-//                        String owner = ur.user();
-//                        List<LastCred> llc = ownerCreds.get(owner);
-//                        if (llc==null) {
-//                            ownerCreds.put(owner, (llc=new ArrayList<>()));
-//                        }
-//                        llc.add(new LastCred(c,last));
-//                    }
-//                } else {
-//                    noOwner.add(new LastCred(c,last));
-//                }
-//            }
-//        }
-//        
-//        boolean bCritical,bNormal,bEarly;
-//        Message msg = new Message();
-//        Notification ownNotf;
-//        StringBuilder logMessage = new StringBuilder();
-//        for (Entry<String,List<LastCred>> es : ownerCreds.entrySet()) {
-//            String owner = es.getKey();
-//            boolean header = true;
-//            try {
-//                Organization org = OrganizationFactory.obtain(env, owner);
-//                Identity user = org.getIdentity(noAvg, owner);
-//                if (!UNKNOWN_ID.equals(owner) && user==null) {
-//                    ps.printf("Invalid Identity: %s\n", owner);
-//                } else {
-//                    logMessage.setLength(0);
-//                    if (maxEmails>emailCount) {
-//                        bCritical=bNormal=bEarly = false;
-//                        email.clear();
-//                        msg.clear();
-//                        email.addTo(user==null?supportEmailAddr:user.email());
-//
-//                        ownNotf = Notification.get(es.getKey(),TYPE.CN);
-//                        if (ownNotf==null) {
-//                            ownNotf = Notification.create(user==null?UNKNOWN_ID:user.fullID(), TYPE.CN);
-//                        }
-//                        last = ownNotf.last;
-//                        // Get Max ID size for formatting purposes
-//                        int length = AAF_INSTANTIATED_MECHID.length();
-//                        for (LastCred lc : es.getValue()) {
-//                            length = Math.max(length, lc.cred.id.length());
-//                        }
-//                        String id_exp_fmt = "\t%-"+length+"s  %15s  %s";
-//
-//                        Collections.sort(es.getValue(),LastCred.COMPARE);
-//                        for (LastCred lc : es.getValue()) {
-//                            if (lc.last.after(must) && lc.last.before(early) && 
-//                                (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) {
-//                                if (!bEarly && header) {
-//                                    msg.line("\tThe following are friendly 2 month reminders, just in case you need to schedule your updates early.  "
-//                                            + "You will be reminded next month\n");
-//                                    msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK);
-//                                    msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3);
-//                                    header = false;
-//                                }
-//                                bEarly = true;
-//                            } else if (lc.last.after(critical) && lc.last.before(must) && 
-//                                    (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) {
-//                                if (!bNormal) {
-//                                    boolean last2wks = lc.last.before(within2Weeks);
-//                                    if (last2wks) {
-//                                        try {
-//                                            Identity supvsr = user.responsibleTo();
-//                                            email.addCC(supvsr.email());
-//                                        } catch (OrganizationException e) {
-//                                            trans.error().log(e, "Supervisor cannot be looked up");
-//                                        }
-//                                    }
-//                                    if (header) {
-//                                        msg.line("\tIt is now important for you to update Passwords all all configurations using them for the following.\n" +
-//                                                (last2wks?"\tNote: Your Supervisor is CCd\n":"\tNote: Your Supervisor will be notified if this is not being done before the last 2 weeks\n"));
-//                                        msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK);
-//                                        msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3);
-//                                    }
-//                                    header = false;
-//                                }
-//                                bNormal=true;
-//                            } else if (lc.last.after(tooLate) && lc.last.before(critical)) { // Email Every Day, with Supervisor
-//                                if (!bCritical && header) {
-//                                    msg.line("\t!!! WARNING: These Credentials will expire in LESS THAN ONE WEEK !!!!\n" +
-//                                             "\tYour supervisor is added to this Email\n");
-//                                    msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK);
-//                                    msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3);
-//                                    header = false;
-//                                }
-//                                bCritical = true;
-//                                try {
-//                                    if (user!=null) {
-//                                        Identity supvsr = user.responsibleTo();
-//                                        if (supvsr!=null) {
-//                                            email.addCC(supvsr.email());
-//                                            supvsr = supvsr.responsibleTo();
-//                                            if (supvsr!=null) {
-//                                                email.addCC(supvsr.email());
-//                                            }
-//                                        }
-//                                    }
-//                                } catch (OrganizationException e) {
-//                                    trans.error().log(e, "Supervisor cannot be looked up");
-//                                }
-//                            }
-//                            if (bEarly || bNormal || bCritical) {
-//                                if (logMessage.length()==0) {
-//                                    logMessage.append("NotifyCredExpiring");
-//                                }
-//                                logMessage.append("\n\t");
-//                                logMessage.append(lc.cred.id);
-//                                logMessage.append('\t');
-//                                logMessage.append(Chrono.dateOnlyStamp(lc.last));
-//                                msg.line(id_exp_fmt, lc.cred.id, Chrono.dateOnlyStamp(lc.last)+"     ",env.getProperty(GUI_URL)+"/creddetail?ns="+Question.domain2ns(lc.cred.id));
-//                            }
-//                        }
-//                        
-//                        if (bEarly || bNormal || bCritical) {
-//                            msg.line(LINE);
-//                            msg.line("Why are you receiving this Notification?\n");
-//                                msg.line("You are the listed owner of one or more AAF Namespaces. ASPR requires that those responsible for "
-//                                        + "applications and their access review them regularly for accuracy.  The AAF WIKI page for AT&T is https://wiki.web.att.com/display/aaf.  "
-//                                        + "You might like https://wiki.web.att.com/display/aaf/AAF+in+a+Nutshell.  More detailed info regarding questions of being a Namespace Owner is available at https://wiki.web.att.com/pages/viewpage.action?pageId=594741363\n");
-//                                msg.line("You may view the Namespaces you listed as Owner for in this AAF Env by viewing the following webpage:\n");
-//                                msg.line("   %s/ns\n\n",env.getProperty(GUI_URL));
-//                            email.msg(msg);
-//                            Result<Void> rv = email.exec(trans, org,"");
-//                            if (rv.isOK()) {
-//                                ++emailCount;
-//                                if (!isDryRun()) {
-//                                    ownNotf.update(noAvg, session, false);
-//                                    // SET LastNotification
-//                                }
-//                                email.log(ps,logMessage.toString());
-//                            } else {
-//                                trans.error().log(rv.errorString());
-//                            }
-//                        }
-//                    }
-//                }
-//            } catch (OrganizationException e) {
-//                trans.info().log(e);
-//            }
-//        }
-        trans.info().printf("%d emails sent for %s", emailCount,batchEnv);
-    }
-    
-    
-    private static class CSVInfo implements CSV.Visitor {
-       private PrintStream out;
-       private Set<String> unsupported;
-       private NotifyCredVisitor credv;
-       private List<LastCred> llc;
-       
-       public CSVInfo(PrintStream out) {
-               this.out = out;
-               credv = new NotifyCredVisitor(llc = new ArrayList<>());
-       }
-       
-               @Override
-               public void visit(List<String> row) throws IOException, CadiException {
-                       
-                       switch(row.get(0)) {
-                          case NotifyCredVisitor.SUPPORTS:
-                                  credv.visit(row);
-                                  break;
-                          default:
-                                  if(unsupported==null) {
-                                          unsupported = new HashSet<String>();
-                                  }
-                                  if(!unsupported.contains(row.get(0))) {
-                                          unsupported.add(row.get(0));
-                                          out.println("Unsupported Type: " + row.get(0));
-                                  }
-                       }
-               }
-    }
-    
-    private static class Contact {
-       public List<String> contacts;
-               private List<UserRole> owners;
-       
-       public Contact(final String ns) {
-               contacts = new ArrayList<>();
-               loadFromNS(ns);
-       }
-       
-       public void loadFromNS(final String ns) {
-               owners = UserRole.getByRole().get(ns+".owner");
-       }
-    }
-    
-    private static class LastCred extends Contact {
-       public final String id;
-       public final int type;
-        public final Date expires;
-        
-        public LastCred(final String id, final String ns, final int type, final Date expires) {
-                       super(ns);
-                       this.id = id;
-                       this.type = type;
-                       this.expires = expires;
-               }
-    }
-    
-    private static class NotifyCredVisitor implements CSV.Visitor {
-       public static final String SUPPORTS = "cred";
-               private final List<LastCred> lastCred;
-       
-       public NotifyCredVisitor(final List<LastCred> lastCred) {
-               this.lastCred = lastCred;
-       }
-       
-               @Override
-               public void visit(List<String> row) throws IOException, CadiException {
-                        try {
-                               lastCred.add(new LastCred(
-                                       row.get(1), 
-                                       row.get(2),
-                                       Integer.parseInt(row.get(3)), 
-                                       Chrono.dateOnlyFmt.parse(row.get(4))
-                                       )
-                               );
-                       } catch (NumberFormatException | ParseException e) {
-                               throw new CadiException(e);
-                       }
-               }
-    }
-    
-    @Override
-    protected void _close(AuthzTrans trans) {
-        session.close();
-        ps.close();
-    }
-}
index dad03ce..a0fdcc5 100644 (file)
@@ -158,8 +158,8 @@ public class Remove extends Batch {
                                                                        if(!x509.get()) {
                                                                                x509.set(true);
                                                                        }
-                                                                       X509.row(cbl.inc(),row);
-                                                                       hdd.target=CertDAO.TABLE
+                                                                       X509.batchDelete(cbl.inc(),row);
+                                                                       hdd.target="x509"
                                                                        hdd.subject=X509.histSubject(row);
                                                                        hdd.memo=X509.histMemo(memoFmt.get(),row);
                                                                        historyDAO.createBatch(cbl.inc(), hdd);
index 16010f7..913ef77 100644 (file)
@@ -25,7 +25,7 @@
 
 major=2
 minor=1
-patch=10
+patch=9
 
 base_version=${major}.${minor}.${patch}