e0c0c0d4dd3edbf32e33d473d48c909b2cf19977
[aaf/authz.git] / auth / auth-cass / src / main / java / org / onap / aaf / auth / dao / cass / ArtiDAO.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.auth.dao.cass;
23
24 import java.io.ByteArrayOutputStream;
25 import java.io.DataInputStream;
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28 import java.nio.ByteBuffer;
29 import java.util.Date;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34 import org.onap.aaf.auth.dao.Bytification;
35 import org.onap.aaf.auth.dao.CassDAOImpl;
36 import org.onap.aaf.auth.dao.Loader;
37 import org.onap.aaf.auth.dao.Streamer;
38 import org.onap.aaf.auth.env.AuthzTrans;
39 import org.onap.aaf.auth.layer.Result;
40 import org.onap.aaf.misc.env.util.Chrono;
41
42 import com.datastax.driver.core.Cluster;
43 import com.datastax.driver.core.Row;
44
45 /**
46  * CredDAO manages credentials. 
47  * @author Jonathan
48  * Date: 7/19/13
49  */
50 public class ArtiDAO extends CassDAOImpl<AuthzTrans,ArtiDAO.Data> {
51     public static final String TABLE = "artifact";
52     
53     private HistoryDAO historyDAO;
54     private PSInfo psByMechID,psByMachine, psByNs;
55     
56     public ArtiDAO(AuthzTrans trans, Cluster cluster, String keyspace) {
57         super(trans, ArtiDAO.class.getSimpleName(),cluster, keyspace, Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
58         init(trans);
59     }
60
61     public ArtiDAO(AuthzTrans trans, HistoryDAO hDao, CacheInfoDAO ciDao) {
62         super(trans, ArtiDAO.class.getSimpleName(),hDao, Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
63         historyDAO = hDao;
64         init(trans);
65     }
66
67     public static final int KEYLIMIT = 2;
68     public static class Data implements Bytification {
69         public String                   mechid;
70         public String                   machine;
71         private Set<String>              type;
72         public String                    sponsor;
73         public String                    ca;
74         public String                    dir;
75         public String                    ns;
76         public String                    os_user;
77         public String                    notify;
78         public Date                      expires;
79         public int                        renewDays;
80         public Set<String>                sans;
81         
82 //      // Getters
83         public Set<String> type(boolean mutable) {
84             if (type == null) {
85                 type = new HashSet<>();
86             } else if (mutable && !(type instanceof HashSet)) {
87                 type = new HashSet<>(type);
88             }
89             return type;
90         }
91
92         public Set<String> sans(boolean mutable) {
93             if (sans == null) {
94                 sans = new HashSet<>();
95             } else if (mutable && !(sans instanceof HashSet)) {
96                 sans = new HashSet<>(sans);
97             }
98             return sans;
99         }
100
101         @Override
102         public ByteBuffer bytify() throws IOException {
103             ByteArrayOutputStream baos = new ByteArrayOutputStream();
104             ArtifactLoader.deflt.marshal(this,new DataOutputStream(baos));
105             return ByteBuffer.wrap(baos.toByteArray());
106         }
107         
108         @Override
109         public void reconstitute(ByteBuffer bb) throws IOException {
110             ArtifactLoader.deflt.unmarshal(this, toDIS(bb));
111         }
112
113         public String toString() {
114             return mechid + ' ' + machine + ' ' + Chrono.dateTime(expires);
115         }
116     }
117
118     private static class ArtifactLoader extends Loader<Data> implements Streamer<Data>{
119         public static final int MAGIC=95829343;
120         public static final int VERSION=1;
121         public static final int BUFF_SIZE=48; // Note: 
122
123         public static final ArtifactLoader deflt = new ArtifactLoader(KEYLIMIT);
124         public ArtifactLoader(int keylimit) {
125             super(keylimit);
126         }
127
128         @Override
129         public Data load(Data data, Row row) {
130             data.mechid = row.getString(0);
131             data.machine = row.getString(1);
132             data.type = row.getSet(2, String.class);
133             data.sponsor = row.getString(3);
134             data.ca = row.getString(4);
135             data.dir = row.getString(5);
136             data.ns = row.getString(6);
137             data.os_user = row.getString(7);
138             data.notify = row.getString(8);
139             data.expires = row.getTimestamp(9);
140             data.renewDays = row.getInt(10);
141             data.sans = row.getSet(11, String.class);
142             return data;
143         }
144
145         @Override
146         protected void key(final Data data, final int idx, Object[] obj) {
147             int i;
148             obj[i=idx] = data.mechid;
149             obj[++i] = data.machine;
150         }
151
152         @Override
153         protected void body(final Data data, final int idx, Object[] obj) {
154             int i;
155             obj[i=idx] = data.type;
156             obj[++i] = data.sponsor;
157             obj[++i] = data.ca;
158             obj[++i] = data.dir;
159             obj[++i] = data.ns;
160             obj[++i] = data.os_user;
161             obj[++i] = data.notify;
162             obj[++i] = data.expires;
163             obj[++i] = data.renewDays;
164             obj[++i] = data.sans;
165         }
166
167         @Override
168         public void marshal(Data data, DataOutputStream os) throws IOException {
169             writeHeader(os,MAGIC,VERSION);
170             writeString(os, data.mechid);
171             writeString(os, data.machine);
172             os.writeInt(data.type.size());
173             for (String s : data.type) {
174                 writeString(os, s);
175             }
176             writeString(os, data.sponsor);
177             writeString(os, data.ca);
178             writeString(os, data.dir);
179             writeString(os, data.ns);
180             writeString(os, data.os_user);
181             writeString(os, data.notify);
182             os.writeLong(data.expires==null?-1:data.expires.getTime());
183             os.writeInt(data.renewDays);
184             if (data.sans!=null) {
185                 os.writeInt(data.sans.size());
186                 for (String s : data.sans) {
187                     writeString(os, s);
188                 }
189             } else {
190                 os.writeInt(0);
191             }
192         }
193
194         @Override
195         public void unmarshal(Data data, DataInputStream is) throws IOException {
196             /*int version = */readHeader(is,MAGIC,VERSION);
197             // If Version Changes between Production runs, you'll need to do a switch Statement, and adequately read in fields
198             byte[] buff = new byte[BUFF_SIZE];
199             data.mechid = readString(is,buff);
200             data.machine = readString(is,buff);
201             int size = is.readInt();
202             data.type = new HashSet<>(size);
203             for (int i=0;i<size;++i) {
204                 data.type.add(readString(is,buff));
205             }
206             data.sponsor = readString(is,buff);
207             data.ca = readString(is,buff);
208             data.dir = readString(is,buff);
209             data.ns = readString(is,buff);
210             data.os_user = readString(is,buff);
211             data.notify = readString(is,buff);
212             long l = is.readLong();
213             data.expires = l<0?null:new Date(l);
214             data.renewDays = is.readInt();
215             size = is.readInt();
216             data.sans = new HashSet<>(size);
217             for (int i=0;i<size;++i) {
218                 data.sans.add(readString(is,buff));
219             }
220         }
221     }
222
223     private void init(AuthzTrans trans) {
224         // Set up sub-DAOs
225         if (historyDAO==null) {
226             historyDAO = new HistoryDAO(trans,this);
227         }
228         
229         String[] helpers = setCRUD(trans, TABLE, Data.class, ArtifactLoader.deflt);
230
231         psByMechID = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE + 
232                 " WHERE mechid = ?", new ArtifactLoader(1) {
233             @Override
234             protected void key(Data data, int idx, Object[] obj) {
235                 obj[idx]=data.type;
236             }
237         },readConsistency);
238
239         psByMachine = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE + 
240                 " WHERE machine = ?", new ArtifactLoader(1) {
241             @Override
242             protected void key(Data data, int idx, Object[] obj) {
243                 obj[idx]=data.type;
244             }
245         },readConsistency);
246
247         psByNs = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE + 
248                 " WHERE ns = ?", new ArtifactLoader(1) {
249             @Override
250             protected void key(Data data, int idx, Object[] obj) {
251                 obj[idx]=data.type;
252             }
253         },readConsistency);
254
255 }
256     
257     
258     public Result<List<Data>> readByMechID(AuthzTrans trans, String mechid) {
259         return psByMechID.read(trans, R_TEXT, new Object[]{mechid});
260     }
261
262     public Result<List<ArtiDAO.Data>> readByMachine(AuthzTrans trans, String machine) {
263         return psByMachine.read(trans, R_TEXT, new Object[]{machine});
264     }
265
266     public Result<List<org.onap.aaf.auth.dao.cass.ArtiDAO.Data>> readByNs(AuthzTrans trans, String ns) {
267         return psByNs.read(trans, R_TEXT, new Object[]{ns});
268     }
269
270     /**
271      * Log Modification statements to History
272      *
273      * @param modified        which CRUD action was done
274      * @param data            entity data that needs a log entry
275      * @param overrideMessage if this is specified, we use it rather than crafting a history message based on data
276      */
277     @Override
278     protected void wasModified(AuthzTrans trans, CRUD modified, Data data, String ... override) {
279         boolean memo = override.length>0 && override[0]!=null;
280         boolean subject = override.length>1 && override[1]!=null;
281
282         HistoryDAO.Data hd = HistoryDAO.newInitedData();
283         hd.user = trans.user();
284         hd.action = modified.name();
285         hd.target = TABLE;
286         hd.subject = subject?override[1]: data.mechid;
287         hd.memo = memo
288                 ? String.format("%s by %s", override[0], hd.user)
289                 : String.format("%sd %s for %s",modified.name(),data.mechid,data.machine);
290         // Detail?
291            if (modified==CRUD.delete) {
292                     try {
293                         hd.reconstruct = data.bytify();
294                     } catch (IOException e) {
295                         trans.error().log(e,"Could not serialize CredDAO.Data");
296                     }
297                 }
298
299         if (historyDAO.create(trans, hd).status!=Status.OK) {
300             trans.error().log("Cannot log to History");
301         }
302     }
303 }