2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
7 * Modification Copyright (c) 2019 IBM
8 * ===========================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END====================================================
24 package org.onap.aaf.auth.dao.cass;
26 import java.io.IOException;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.UUID;
31 import org.onap.aaf.auth.dao.CassAccess;
32 import org.onap.aaf.auth.dao.CassDAOImpl;
33 import org.onap.aaf.auth.dao.Loader;
34 import org.onap.aaf.auth.env.AuthzTrans;
35 import org.onap.aaf.auth.layer.Result;
36 import org.onap.aaf.misc.env.APIException;
37 import org.onap.aaf.misc.env.Env;
38 import org.onap.aaf.misc.env.TimeTaken;
39 import org.onap.aaf.misc.env.util.Chrono;
41 import com.datastax.driver.core.Cluster;
42 import com.datastax.driver.core.ResultSet;
43 import com.datastax.driver.core.Row;
44 import com.datastax.driver.core.exceptions.DriverException;
47 public class ApprovalDAO extends CassDAOImpl<AuthzTrans,ApprovalDAO.Data> {
48 public static final String PENDING = "pending";
49 public static final String DENIED = "denied";
50 public static final String APPROVED = "approved";
52 private static final String TABLE = "approval";
53 private static final String TABLELOG = "approved";
54 private HistoryDAO historyDAO;
55 private PSInfo psByUser;
56 private PSInfo psByApprover;
57 private PSInfo psByTicket;
58 private PSInfo psByStatus;
61 public ApprovalDAO(AuthzTrans trans, Cluster cluster, String keyspace) {
62 super(trans, ApprovalDAO.class.getSimpleName(),cluster,keyspace,Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
63 historyDAO = new HistoryDAO(trans, this);
68 public ApprovalDAO(AuthzTrans trans, HistoryDAO hDAO) {
69 super(trans, ApprovalDAO.class.getSimpleName(),hDAO,Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
74 private static final int KEYLIMIT = 1;
75 public static class Data {
79 public String approver;
83 public String operation;
84 // public Date last_notified;
88 private static class ApprovalLoader extends Loader<Data> {
89 public static final ApprovalLoader deflt = new ApprovalLoader(KEYLIMIT);
91 public ApprovalLoader(int keylimit) {
96 public Data load(Data data, Row row) {
97 data.id = row.getUUID(0);
98 data.ticket = row.getUUID(1);
99 data.user = row.getString(2);
100 data.approver = row.getString(3);
101 data.type = row.getString(4);
102 data.status = row.getString(5);
103 data.memo = row.getString(6);
104 data.operation = row.getString(7);
105 // data.last_notified = row.getTimestamp(8);
106 // This is used to get "WRITETIME(STATUS)" from Approval, which gives us an "updated"
107 if (row.getColumnDefinitions().size()>8) {
108 // Rows reported in MicroSeconds
109 data.updated = new Date(row.getLong(8)/1000);
115 protected void key(Data data, int idx, Object[] obj) {
120 protected void body(Data data, int _idx, Object[] obj) {
122 obj[idx]=data.ticket;
123 obj[++idx]=data.user;
124 obj[++idx]=data.approver;
125 obj[++idx]=data.type;
126 obj[++idx]=data.status;
127 obj[++idx]=data.memo;
128 obj[++idx]=data.operation;
129 // obj[++idx]=data.last_notified;
133 private void init(AuthzTrans trans) {
134 String[] helpers = setCRUD(trans, TABLE, Data.class, ApprovalLoader.deflt,8);
135 psByUser = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
136 " WHERE user = ?", new ApprovalLoader(1) {
138 protected void key(Data data, int idx, Object[] obj) {
143 psByApprover = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
144 " WHERE approver = ?", new ApprovalLoader(1) {
146 protected void key(Data data, int idx, Object[] obj) {
147 obj[idx]=data.approver;
151 psByTicket = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
152 " WHERE ticket = ?", new ApprovalLoader(1) {
154 protected void key(Data data, int idx, Object[] obj) {
155 obj[idx]=data.ticket;
159 psByStatus = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + ", WRITETIME(status) FROM " + TABLE +
160 " WHERE status = ?", new ApprovalLoader(1) {
162 protected void key(Data data, int idx, Object[] obj) {
163 obj[idx]=data.status;
171 * @see org.onap.aaf.auth.dao.CassDAOImpl#create(com.att.inno.env.TransStore, java.lang.Object)
174 public Result<Data> create(AuthzTrans trans, Data data) {
175 // If ID is not set (typical), create one.
177 data.id = Chrono.dateToUUID(System.currentTimeMillis());
179 Result<ResultSet> rs = createPS.exec(trans, C_TEXT, data);
181 return Result.err(rs);
183 return Result.ok(data);
187 public Result<List<ApprovalDAO.Data>> readByUser(AuthzTrans trans, String user) {
188 return psByUser.read(trans, R_TEXT, new Object[]{user});
191 public Result<List<ApprovalDAO.Data>> readByApprover(AuthzTrans trans, String approver) {
192 return psByApprover.read(trans, R_TEXT, new Object[]{approver});
195 public Result<List<ApprovalDAO.Data>> readByTicket(AuthzTrans trans, UUID ticket) {
196 return psByTicket.read(trans, R_TEXT, new Object[]{ticket});
199 public Result<List<ApprovalDAO.Data>> readByStatus(AuthzTrans trans, String status) {
200 return psByStatus.read(trans, R_TEXT, new Object[]{status});
204 * @see org.onap.aaf.auth.dao.CassDAOImpl#delete(com.att.inno.env.TransStore, java.lang.Object, boolean)
207 public Result<Void> delete(AuthzTrans trans, Data data, boolean reread) {
208 if (reread || data.status == null) { // if Memo is empty, likely not full record
209 Result<ResultSet> rd = readPS.exec(trans, R_TEXT, data);
211 return Result.err(rd);
213 ApprovalLoader.deflt.load(data, rd.value.one());
215 if (APPROVED.equals(data.status) || DENIED.equals(data.status)) {
216 StringBuilder sb = new StringBuilder("BEGIN BATCH\n");
217 sb.append("INSERT INTO ");
219 sb.append(" (id,user,approver,type,status,memo,operation) VALUES (");
222 sb.append(data.user);
224 sb.append(data.approver);
226 sb.append(data.type);
228 sb.append(data.status);
230 sb.append(data.memo.replace("'", "''"));
232 sb.append(data.operation);
234 sb.append("DELETE FROM ");
236 sb.append(" WHERE id=");
239 sb.append("APPLY BATCH;\n");
240 TimeTaken tt = trans.start("DELETE APPROVAL",Env.REMOTE);
243 getSession(trans).executeAsync(sb.toString());
246 getSession(trans).execute(sb.toString());
249 } catch (DriverException | APIException | IOException e) {
250 reportPerhapsReset(trans,e);
251 return Result.err(Result.ERR_Backend, CassAccess.ERR_ACCESS_MSG);
256 return super.delete(trans, data, false);
263 * Log Modification statements to History
265 * @param modified which CRUD action was done
266 * @param data entity data that needs a log entry
267 * @param overrideMessage if this is specified, we use it rather than crafting a history message based on data
270 protected void wasModified(AuthzTrans trans, CRUD modified, Data data, String ... override) {
271 boolean memo = override.length>0 && override[0]!=null;
272 boolean subject = override.length>1 && override[1]!=null;
274 HistoryDAO.Data hd = HistoryDAO.newInitedData();
275 hd.user = trans.user();
276 hd.action = modified.name();
278 hd.subject = subject?override[1]:data.user + "|" + data.approver;
280 ? String.format("%s by %s", override[0], hd.user)
281 : (modified.name() + "d approval for " + data.user);
284 if (historyDAO.create(trans, hd).status!=Status.OK) {
285 trans.error().log("Cannot log to History");