2 * ============LICENSE_START====================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
22 package org.onap.aaf.auth.dao.cass;
24 import java.io.IOException;
25 import java.util.Date;
26 import java.util.List;
27 import java.util.UUID;
29 import org.onap.aaf.auth.dao.CassAccess;
30 import org.onap.aaf.auth.dao.CassDAOImpl;
31 import org.onap.aaf.auth.dao.Loader;
32 import org.onap.aaf.auth.env.AuthzTrans;
33 import org.onap.aaf.auth.layer.Result;
34 import org.onap.aaf.misc.env.APIException;
35 import org.onap.aaf.misc.env.Env;
36 import org.onap.aaf.misc.env.TimeTaken;
37 import org.onap.aaf.misc.env.util.Chrono;
39 import com.datastax.driver.core.Cluster;
40 import com.datastax.driver.core.ResultSet;
41 import com.datastax.driver.core.Row;
42 import com.datastax.driver.core.exceptions.DriverException;
45 public class ApprovalDAO extends CassDAOImpl<AuthzTrans,ApprovalDAO.Data> {
46 public static final String PENDING = "pending";
47 public static final String DENIED = "denied";
48 public static final String APPROVED = "approved";
50 private static final String TABLE = "approval";
51 private static final String TABLELOG = "approved";
52 private HistoryDAO historyDAO;
53 private PSInfo psByUser, psByApprover, psByTicket, psByStatus;
56 public ApprovalDAO(AuthzTrans trans, Cluster cluster, String keyspace) {
57 super(trans, ApprovalDAO.class.getSimpleName(),cluster,keyspace,Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
58 historyDAO = new HistoryDAO(trans, this);
63 public ApprovalDAO(AuthzTrans trans, HistoryDAO hDAO) {
64 super(trans, ApprovalDAO.class.getSimpleName(),hDAO,Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
69 private static final int KEYLIMIT = 1;
70 public static class Data {
74 public String approver;
78 public String operation;
79 // public Date last_notified;
83 private static class ApprovalLoader extends Loader<Data> {
84 public static final ApprovalLoader deflt = new ApprovalLoader(KEYLIMIT);
86 public ApprovalLoader(int keylimit) {
91 public Data load(Data data, Row row) {
92 data.id = row.getUUID(0);
93 data.ticket = row.getUUID(1);
94 data.user = row.getString(2);
95 data.approver = row.getString(3);
96 data.type = row.getString(4);
97 data.status = row.getString(5);
98 data.memo = row.getString(6);
99 data.operation = row.getString(7);
100 // data.last_notified = row.getTimestamp(8);
101 // This is used to get "WRITETIME(STATUS)" from Approval, which gives us an "updated"
102 if (row.getColumnDefinitions().size()>8) {
103 // Rows reported in MicroSeconds
104 data.updated = new Date(row.getLong(8)/1000);
110 protected void key(Data data, int idx, Object[] obj) {
115 protected void body(Data data, int _idx, Object[] obj) {
117 obj[idx]=data.ticket;
118 obj[++idx]=data.user;
119 obj[++idx]=data.approver;
120 obj[++idx]=data.type;
121 obj[++idx]=data.status;
122 obj[++idx]=data.memo;
123 obj[++idx]=data.operation;
124 // obj[++idx]=data.last_notified;
128 private void init(AuthzTrans trans) {
129 String[] helpers = setCRUD(trans, TABLE, Data.class, ApprovalLoader.deflt,8);
130 psByUser = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
131 " WHERE user = ?", new ApprovalLoader(1) {
133 protected void key(Data data, int idx, Object[] obj) {
138 psByApprover = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
139 " WHERE approver = ?", new ApprovalLoader(1) {
141 protected void key(Data data, int idx, Object[] obj) {
142 obj[idx]=data.approver;
146 psByTicket = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
147 " WHERE ticket = ?", new ApprovalLoader(1) {
149 protected void key(Data data, int idx, Object[] obj) {
150 obj[idx]=data.ticket;
154 psByStatus = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
155 " WHERE status = ?", new ApprovalLoader(1) {
157 protected void key(Data data, int idx, Object[] obj) {
158 obj[idx]=data.status;
166 * @see org.onap.aaf.auth.dao.CassDAOImpl#create(com.att.inno.env.TransStore, java.lang.Object)
169 public Result<Data> create(AuthzTrans trans, Data data) {
170 // If ID is not set (typical), create one.
172 data.id = Chrono.dateToUUID(System.currentTimeMillis());
174 Result<ResultSet> rs = createPS.exec(trans, C_TEXT, data);
176 return Result.err(rs);
178 return Result.ok(data);
182 public Result<List<ApprovalDAO.Data>> readByUser(AuthzTrans trans, String user) {
183 return psByUser.read(trans, R_TEXT, new Object[]{user});
186 public Result<List<ApprovalDAO.Data>> readByApprover(AuthzTrans trans, String approver) {
187 return psByApprover.read(trans, R_TEXT, new Object[]{approver});
190 public Result<List<ApprovalDAO.Data>> readByTicket(AuthzTrans trans, UUID ticket) {
191 return psByTicket.read(trans, R_TEXT, new Object[]{ticket});
194 public Result<List<ApprovalDAO.Data>> readByStatus(AuthzTrans trans, String status) {
195 return psByStatus.read(trans, R_TEXT, new Object[]{status});
199 * @see org.onap.aaf.auth.dao.CassDAOImpl#delete(com.att.inno.env.TransStore, java.lang.Object, boolean)
202 public Result<Void> delete(AuthzTrans trans, Data data, boolean reread) {
203 if (reread || data.status == null) { // if Memo is empty, likely not full record
204 Result<ResultSet> rd = readPS.exec(trans, R_TEXT, data);
206 return Result.err(rd);
208 ApprovalLoader.deflt.load(data, rd.value.one());
210 if ("approved".equals(data.status) || "denied".equals(data.status)) {
211 StringBuilder sb = new StringBuilder("BEGIN BATCH\n");
212 sb.append("INSERT INTO ");
214 sb.append(" (id,user,approver,type,status,memo,operation) VALUES (");
216 sb.append(",'"); sb.append(data.user);
217 sb.append("','"); sb.append(data.approver);
218 sb.append("','"); sb.append(data.type);
219 sb.append("','"); sb.append(data.status);
220 sb.append("','"); sb.append(data.memo.replace("'", "''"));
221 sb.append("','"); sb.append(data.operation);
223 sb.append("DELETE FROM ");
225 sb.append(" WHERE id=");
228 sb.append("APPLY BATCH;\n");
229 TimeTaken tt = trans.start("DELETE APPROVAL",Env.REMOTE);
232 getSession(trans).executeAsync(sb.toString());
235 getSession(trans).execute(sb.toString());
238 } catch (DriverException | APIException | IOException e) {
239 reportPerhapsReset(trans,e);
240 return Result.err(Result.ERR_Backend, CassAccess.ERR_ACCESS_MSG);
245 return super.delete(trans, data, false);
252 * Log Modification statements to History
254 * @param modified which CRUD action was done
255 * @param data entity data that needs a log entry
256 * @param overrideMessage if this is specified, we use it rather than crafting a history message based on data
259 protected void wasModified(AuthzTrans trans, CRUD modified, Data data, String ... override) {
260 boolean memo = override.length>0 && override[0]!=null;
261 boolean subject = override.length>1 && override[1]!=null;
263 HistoryDAO.Data hd = HistoryDAO.newInitedData();
264 hd.user = trans.user();
265 hd.action = modified.name();
267 hd.subject = subject?override[1]:data.user + "|" + data.approver;
269 ? String.format("%s by %s", override[0], hd.user)
270 : (modified.name() + "d approval for " + data.user);
273 if (historyDAO.create(trans, hd).status!=Status.OK) {
274 trans.error().log("Cannot log to History");