Add a MassMail Batch Program
[aaf/authz.git] / auth / auth-batch / src / main / java / org / onap / aaf / auth / batch / helpers / UserRole.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 IBM.
7  * ===========================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END====================================================
20  *
21  */
22
23 package org.onap.aaf.auth.batch.helpers;
24
25 import java.io.IOException;
26 import java.io.PrintStream;
27 import java.util.ArrayList;
28 import java.util.Date;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.SortedMap;
32 import java.util.TreeMap;
33
34 import org.onap.aaf.auth.dao.cass.UserRoleDAO;
35 import org.onap.aaf.auth.dao.cass.UserRoleDAO.Data;
36 import org.onap.aaf.auth.env.AuthzTrans;
37 import org.onap.aaf.cadi.CadiException;
38 import org.onap.aaf.cadi.util.CSV;
39 import org.onap.aaf.misc.env.Env;
40 import org.onap.aaf.misc.env.TimeTaken;
41 import org.onap.aaf.misc.env.Trans;
42 import org.onap.aaf.misc.env.util.Chrono;
43
44 import com.datastax.driver.core.ResultSet;
45 import com.datastax.driver.core.Row;
46 import com.datastax.driver.core.Session;
47 import com.datastax.driver.core.SimpleStatement;
48 import com.datastax.driver.core.Statement;
49
50 public class UserRole implements Cloneable, CacheChange.Data  {
51
52     public static final String UR = "ur";
53     public static final String APPROVE_UR = "ur";
54
55     private static final String SEPARATOR = "\",\"";
56
57     // CACHE Calling
58     private static final String LOG_FMT = "%s UserRole - %s: %s-%s (%s, %s) expiring %s";
59     private static final String REPLAY_FMT = "%s|%s|%s|%s|%s\n";
60     private static final String DELETE_FMT = "# %s\n" + REPLAY_FMT;
61
62     private static final List<UserRole> data = new ArrayList<>();
63     private static final SortedMap<String,List<UserRole>> byUser = new TreeMap<>();
64     private static final SortedMap<String,List<UserRole>> byRole = new TreeMap<>();
65     private static final CacheChange<UserRole> cache = new CacheChange<>();
66     private static PrintStream urDelete = System.out;
67     private static PrintStream urRecover = System.err;
68     private static int totalLoaded;
69     private int deleted;
70     private Data urdd;
71
72     public static final Creator<UserRole> v2_0_11 = new Creator<UserRole>() {
73         @Override
74         public UserRole create(Row row) {
75             return new UserRole(row.getString(0), row.getString(1), row.getString(2),row.getString(3),row.getTimestamp(4));
76         }
77
78         @Override
79         public String select() {
80             return "select user,role,ns,rname,expires from authz.user_role";
81         }
82     };
83
84     public UserRole(String user, String ns, String rname, Date expires) {
85         urdd = new UserRoleDAO.Data();
86         urdd.user = user;
87         urdd.role = ns + '.' + rname;
88         urdd.ns = ns;
89         urdd.rname = rname;
90         urdd.expires = expires;
91     }
92
93     public UserRole(String user, String role, String ns, String rname, Date expires) {
94         urdd = new UserRoleDAO.Data();
95         urdd.user = user;
96         urdd.role = role;
97         urdd.ns = ns;
98         urdd.rname = rname;
99         urdd.expires = expires;
100     }
101
102     public static List<UserRole> getData() {
103         return data;
104     }
105
106     public static SortedMap<String, List<UserRole>> getByUser() {
107         return byUser;
108     }
109
110     public static SortedMap<String, List<UserRole>> getByRole() {
111         return byRole;
112     }
113
114     public static void load(Trans trans, Session session, Creator<UserRole> creator) {
115         load(trans,session,creator,null,new DataLoadVisitor());
116     }
117
118     public static void load(Trans trans, Session session, Creator<UserRole> creator, Visitor<UserRole> visitor ) {
119         load(trans,session,creator,null,visitor);
120     }
121
122     public static void loadOneRole(Trans trans, Session session, Creator<UserRole> creator, String role, Visitor<UserRole> visitor) {
123         load(trans,session,creator,"role='" + role +"' ALLOW FILTERING;",visitor);
124     }
125
126     public static void loadOneUser(Trans trans, Session session, Creator<UserRole> creator, String user, Visitor<UserRole> visitor ) {
127         load(trans,session,creator,"user='" + user + '\'',visitor);
128     }
129
130     public static void load(Trans trans, CSV csv, Creator<UserRole> creator, Visitor<UserRole> visitor) throws IOException, CadiException {
131 //        public UserRole(String user, String role, String ns, String rname, Date expires) {
132         csv.visit( row ->
133             visitor.visit(new UserRole(row.get(1),row.get(2),row.get(3),row.get(4),
134                 new Date(Long.parseLong(row.get(6)))))
135         );
136     }
137
138     public static void load(Trans trans, Session session, Creator<UserRole> creator, String where, Visitor<UserRole> visitor) {
139         String query = creator.query(where);
140         trans.debug().log( "query: " + query );
141         TimeTaken tt = trans.start("Read UserRoles", Env.REMOTE);
142
143         ResultSet results;
144         try {
145             Statement stmt = new SimpleStatement( query );
146             results = session.execute(stmt);
147         } finally {
148             tt.done();
149         }
150         try {
151             tt = trans.start("Load UserRole", Env.SUB);
152             try {
153                 iterateResults(creator, results.iterator(), visitor);
154             } finally {
155                 tt.done();
156             }
157         } finally {
158             trans.debug().log("Loaded",totalLoaded,"UserRoles");
159         }
160     }
161
162     private static void iterateResults(Creator<UserRole> creator, Iterator<Row> iter, Visitor<UserRole> visit ) {
163         Row row;
164         while (iter.hasNext()) {
165             ++totalLoaded;
166             row = iter.next();
167             UserRole ur = creator.create(row);
168             visit.visit(ur);
169         }
170     }
171
172     public static class DataLoadVisitor implements Visitor<UserRole> {
173         @Override
174         public void visit(UserRole ur) {
175             data.add(ur);
176
177             List<UserRole> lur = byUser.get(ur.urdd.user);
178             if (lur==null) {
179                 lur = new ArrayList<>();
180                 byUser.put(ur.urdd.user, lur);
181             }
182             lur.add(ur);
183
184             lur = byRole.get(ur.urdd.role);
185             if (lur==null) {
186                 lur = new ArrayList<>();
187                 byRole.put(ur.urdd.role, lur);
188             }
189             lur.add(ur);
190         }
191     }
192
193     public int totalLoaded() {
194         return totalLoaded;
195     }
196
197     public int deleted() {
198         return deleted;
199     }
200
201     @Override
202     public void expunge() {
203         data.remove(this);
204
205         List<UserRole> lur = byUser.get(urdd.user);
206         if (lur!=null) {
207             lur.remove(this);
208         }
209
210         lur = byRole.get(urdd.role);
211         if (lur!=null) {
212             lur.remove(this);
213         }
214     }
215
216     public static void setDeleteStream(PrintStream ds) {
217         urDelete = ds;
218     }
219
220     public static void setRecoverStream(PrintStream ds) {
221         urRecover = ds;
222     }
223
224     public static long count(Trans trans, Session session) {
225         String query = "select count(*) from authz.user_role LIMIT 1000000;";
226         trans.info().log( "query: " + query );
227         TimeTaken tt = trans.start("Count Namespaces", Env.REMOTE);
228         ResultSet results;
229         try {
230             Statement stmt = new SimpleStatement(query).setReadTimeoutMillis(12000);
231             results = session.execute(stmt);
232             return results.one().getLong(0);
233         } finally {
234             tt.done();
235         }
236     }
237
238     public UserRoleDAO.Data urdd() {
239         return urdd;
240     }
241
242     public String user() {
243         return urdd.user;
244     }
245
246     public String role() {
247         return urdd.role;
248     }
249
250     public String ns() {
251         return urdd.ns;
252     }
253
254     public String rname() {
255         return urdd.rname;
256     }
257
258     public Date expires() {
259         return urdd.expires;
260     }
261
262     public void expires(Date time) {
263         urdd.expires = time;
264     }
265
266     public String toString() {
267         return "\"" + urdd.user + SEPARATOR + urdd.role + SEPARATOR + urdd.ns + SEPARATOR + urdd.rname + SEPARATOR
268             + Chrono.dateOnlyStamp(urdd.expires);
269     }
270
271     public static UserRole get(String u, String r) {
272         List<UserRole> lur = byUser.get(u);
273         if (lur!=null) {
274             for (UserRole ur : lur) {
275
276                 if (ur.urdd.role.equals(r)) {
277                     return ur;
278                 }
279             }
280         }
281         return null;
282     }
283
284     // SAFETY - DO NOT DELETE USER ROLES DIRECTLY FROM BATCH FILES!!!
285     // We write to a file, and validate.  If the size is iffy, we email Support
286     public void delayDelete(AuthzTrans trans, String text, boolean dryRun) {
287         String dt = Chrono.dateTime(urdd.expires);
288         if (dryRun) {
289             trans.info().printf(LOG_FMT,text,"Would Delete",urdd.user,urdd.role,urdd.ns,urdd.rname,dt);
290         } else {
291             trans.info().printf(LOG_FMT,text,"Staged Deletion",urdd.user,urdd.role,urdd.ns,urdd.rname,dt);
292         }
293         urDelete.printf(DELETE_FMT,text,urdd.user,urdd.role,dt,urdd.ns,urdd.rname);
294         urRecover.printf(REPLAY_FMT,urdd.user,urdd.role,dt,urdd.ns,urdd.rname);
295
296         cache.delayedDelete(this);
297         ++deleted;
298     }
299
300
301     /**
302      * Calls expunge() for all deleteCached entries
303      */
304     public static void resetLocalData() {
305         cache.resetLocalData();
306     }
307
308     public void row(final CSV.Writer csvw, String tag) {
309         csvw.row(tag,user(),role(),ns(),rname(),Chrono.dateOnlyStamp(expires()),expires().getTime());
310     }
311
312     public void row(final CSV.Writer csvw, String tag, String reason) {
313         csvw.row(tag,user(),role(),ns(),rname(),Chrono.dateOnlyStamp(expires()),expires().getTime(),reason);
314     }
315
316     public static Data row(List<String> row) {
317         Data data = new Data();
318         data.user = row.get(1);
319         data.role = row.get(2);
320         data.ns = row.get(3);
321         data.rname = row.get(4);
322         data.expires = new Date(Long.parseLong(row.get(6)));
323         return data;
324     }
325
326     public static void batchDelete(StringBuilder sb, List<String> row) {
327         sb.append("DELETE from authz.user_role WHERE user='");
328         sb.append(row.get(1));
329         sb.append("' AND role='");
330         sb.append(row.get(2));
331         sb.append("';\n");
332     }
333
334     public static void batchExtend(StringBuilder sb, List<String> row, Date newDate ) {
335         sb.append("UPDATE authz.user_role SET expires='");
336         sb.append(Chrono.dateTime(newDate));
337         sb.append("' WHERE user='");
338         sb.append(row.get(1));
339         sb.append("' AND role='");
340         sb.append(row.get(2));
341         sb.append("';\n");
342     }
343
344     public void batchExtend(StringBuilder sb, Date newDate) {
345         sb.append("UPDATE authz.user_role SET expires='");
346         sb.append(Chrono.dateTime(newDate));
347         sb.append("' WHERE user='");
348         sb.append(user());
349         sb.append("' AND role='");
350         sb.append(role());
351         sb.append("';\n");
352     }
353
354     public void batchUpdateExpires(StringBuilder sb) {
355         sb.append("UPDATE authz.user_role SET expires='");
356         sb.append(Chrono.dateTime(expires()));
357         sb.append("' WHERE user='");
358         sb.append(user());
359         sb.append("' AND role='");
360         sb.append(role());
361         sb.append("';\n");
362     }
363
364     public static String histMemo(String fmt, List<String> row) {
365         String reason;
366         if(row.size()>7) { // Reason included
367             reason = String.format("%s removed from %s because %s",
368                     row.get(1),row.get(2),row.get(7));
369         } else {
370             reason = String.format(fmt, row.get(1),row.get(2), row.get(5));
371         }
372         return reason;
373     }
374
375     public static String histSubject(List<String> row) {
376         return row.get(1) + '|' + row.get(2);
377     }
378
379     public static void clear() {
380         data.clear();
381         byUser.clear();
382         byRole.clear();
383         cache.resetLocalData();
384
385     }
386 }