Improve Batches
[aaf/authz.git] / auth / auth-gui / src / main / java / org / onap / aaf / auth / gui / pages / ApprovalForm.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.gui.pages;
23
24 import java.io.IOException;
25 import java.net.ConnectException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Comparator;
29 import java.util.List;
30
31 import org.onap.aaf.auth.env.AuthzEnv;
32 import org.onap.aaf.auth.env.AuthzTrans;
33 import org.onap.aaf.auth.gui.AAF_GUI;
34 import org.onap.aaf.auth.gui.BreadCrumbs;
35 import org.onap.aaf.auth.gui.Form;
36 import org.onap.aaf.auth.gui.NamedCode;
37 import org.onap.aaf.auth.gui.Page;
38 import org.onap.aaf.auth.gui.Table;
39 import org.onap.aaf.auth.gui.Table.Cells;
40 import org.onap.aaf.auth.gui.table.AbsCell;
41 import org.onap.aaf.auth.gui.table.ButtonCell;
42 import org.onap.aaf.auth.gui.table.RadioCell;
43 import org.onap.aaf.auth.gui.table.RefCell;
44 import org.onap.aaf.auth.gui.table.TableData;
45 import org.onap.aaf.auth.gui.table.TextAndRefCell;
46 import org.onap.aaf.auth.gui.table.TextCell;
47 import org.onap.aaf.auth.org.Organization;
48 import org.onap.aaf.auth.org.OrganizationFactory;
49 import org.onap.aaf.auth.org.Organization.Identity;
50 import org.onap.aaf.cadi.CadiException;
51 import org.onap.aaf.cadi.client.Future;
52 import org.onap.aaf.cadi.client.Rcli;
53 import org.onap.aaf.cadi.client.Retryable;
54 import org.onap.aaf.misc.env.APIException;
55 import org.onap.aaf.misc.env.Env;
56 import org.onap.aaf.misc.env.Slot;
57 import org.onap.aaf.misc.env.TimeTaken;
58 import org.onap.aaf.misc.xgen.Cache;
59 import org.onap.aaf.misc.xgen.DynamicCode;
60 import org.onap.aaf.misc.xgen.Mark;
61 import org.onap.aaf.misc.xgen.html.HTMLGen;
62
63 import aaf.v2_0.Approval;
64 import aaf.v2_0.Approvals;
65
66 public class ApprovalForm extends Page {
67     // Package on purpose
68     static final String NAME="Approvals";
69     static final String HREF = "/gui/approve";
70     static final String[] FIELDS = new String[] {"line[]","user","delegate_of"};
71     
72     
73     public ApprovalForm(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
74         super(gui.env,NAME,HREF, FIELDS,
75
76             new BreadCrumbs(breadcrumbs),
77             new NamedCode(false, "filterByUser") {
78                 @Override
79                 public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
80                     cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
81                         @Override
82                         public void code(final AAF_GUI gui, final AuthzTrans trans,    final Cache<HTMLGen> cache, final HTMLGen hgen)    throws APIException, IOException {
83                             String user = trans.get(trans.env().slot(NAME+".user"),"");
84                             hgen.incr("p", "class=userFilter")
85                                 .text("Filter by User:")
86                                 .tagOnly("input", "type=text", "value="+user, "id=userTextBox")
87                                 .tagOnly("input", "type=button", "onclick=userFilter('"+HREF+"');", "value=Go!")
88                                 .end();
89                                 }
90                     });
91                 }
92             },
93             new Form(true,new Table<AAF_GUI,AuthzTrans>("Approval Requests", gui.env.newTransNoAvg(),new Model(gui.env),"class=stdform"))
94                 .preamble("The following requires your Approval to proceed in the AAF System.</p><p class=subtext>Hover on Identity for Name; click for WebPhone; If Deny is the only option, User is no longer valid."),
95             new NamedCode(false, "selectAlljs") {
96                 @Override
97                 public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
98                     Mark jsStart = new Mark();
99                     hgen.js(jsStart);
100                     hgen.text("function selectAll(radioClass) {");
101                     hgen.text("var radios = document.querySelectorAll(\".\"+radioClass);");
102                     hgen.text("for (i = 0; i < radios.length; i++) {");
103                     hgen.text("radios[i].checked = true;");
104                     hgen.text("}");
105                     hgen.text("}");
106                     hgen.end(jsStart);
107                 }
108             });
109     }
110     
111     /**
112      * Implement the Table Content for Approvals
113      * 
114      * @author Jonathan
115      *
116      */
117     private static class Model extends TableData<AAF_GUI,AuthzTrans> {
118         //TODO come up with a generic way to do ILM Info (people page)
119         private static final String TODO_ILM_INFO = "TODO: ILM Info";
120         
121         
122         private static final String[] headers = new String[] {"Identity","Request","Approve","Deny"};
123         private Slot sUser;
124         private Slot sAsDelegate;
125         
126         public Model(AuthzEnv env) {
127             sUser = env.slot(NAME+".user");
128             sAsDelegate = env.slot(NAME+".delegate_of");
129         }
130         
131         @Override
132         public String[] headers() {
133             return headers;
134         }
135         
136         @Override
137         public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
138             final String userParam = trans.get(sUser, null);
139             final String asDelegate = trans.get(sAsDelegate, trans.user());
140             ArrayList<AbsCell[]> rv = new ArrayList<>();
141             String msg = null;
142             TimeTaken tt = trans.start("AAF Get Approvals for Approver",Env.REMOTE);
143             try {
144                 final List<Approval> pendingApprovals = new ArrayList<>();
145                 final List<Integer> beginIndicesPerApprover = new ArrayList<>();
146                 int numLeft = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Integer>() {
147                     @Override
148                     public Integer code(Rcli<?> client) throws CadiException, ConnectException, APIException {
149                         Future<Approvals> fa = client.read("/authz/approval/approver/"+asDelegate,gui.getDF(Approvals.class));
150                         int numLeft = 0;
151                         if (fa.get(AAF_GUI.TIMEOUT)) {
152                             
153                             if (fa.value!=null) {
154                                 for (Approval appr : fa.value.getApprovals()) {
155                                     if ("pending".equals(appr.getStatus())) {
156                                         if (userParam!=null && !appr.getUser().equalsIgnoreCase(userParam)) {
157                                                 numLeft++;
158                                                 continue;
159                                         }
160                                         pendingApprovals.add(appr);
161                                     }
162                                 }
163                             }
164                             
165                             String prevApprover = null;
166                             int overallIndex = 0;
167                                 
168                             for (Approval appr : pendingApprovals) {
169                                 String currApprover = appr.getApprover();
170                                 if (!currApprover.equals(prevApprover)) {
171                                     prevApprover = currApprover;
172                                     beginIndicesPerApprover.add(overallIndex);
173                                 }
174                                 overallIndex++;
175                             }
176                         }
177                         return numLeft;
178                     }
179                 });
180                 
181                 if (!pendingApprovals.isEmpty()) {
182                     // Only add select all links if we have approvals
183                     AbsCell[] selectAllRow = new AbsCell[] {
184                             AbsCell.Null,
185                             AbsCell.Null,
186                             new ButtonCell("all", "onclick=selectAll('approve')", "class=selectAllButton"),
187                             new ButtonCell("all", "onclick=selectAll('deny')", "class=selectAllButton")
188                         };
189                     rv.add(selectAllRow);
190                 }
191                         
192                 int line=-1;
193                 
194                 while (!beginIndicesPerApprover.isEmpty()) {
195                     int beginIndex = beginIndicesPerApprover.remove(0);
196                     int endIndex = (beginIndicesPerApprover.isEmpty()?pendingApprovals.size():beginIndicesPerApprover.get(0));
197                     List<Approval> currApproverList = pendingApprovals.subList(beginIndex, endIndex);
198                     
199                     Identity iapprover = trans.org().getIdentity(trans,currApproverList.get(0).getApprover());
200                     if(iapprover==null) {
201                         rv.add(new AbsCell[] {
202                                         new TextCell(currApproverList.get(0).getApprover() + " is not part of Organization",
203                                         new String[] {"colspan=4", "class=head"})
204                         });
205                     } else {
206                         if (!iapprover.fullID().equals(trans.user())) {
207                             
208                                 AbsCell[] approverHeader;
209         //                        if (domainOfUser.equals(domainOfApprover)) {
210         //                            approverHeader = new AbsCell[] { 
211         //                                    new TextAndRefCell("Approvals Delegated to Me by ", currApproverFull,
212         //                                            TODO_ILM_INFO + currApproverShort, 
213         //                                            true,
214         //                                            new String[] {"colspan=4", "class=head"})
215         //                            };
216         //                        } else {
217                                     approverHeader = new AbsCell[] { 
218                                             new TextCell("Approvals Delegated to Me by " + iapprover.fullName() 
219                                                + '(' + iapprover.id() +')',
220                                                     new String[] {"colspan=4", "class=head"})
221                                     };
222         //                        }
223                                 rv.add(approverHeader);
224                             }
225                             
226                             // Sort by User Requesting
227                             Collections.sort(currApproverList, new Comparator<Approval>() {
228                                 @Override
229                                 public int compare(Approval a1, Approval a2) {
230                                     return a1.getUser().compareTo(a2.getUser());
231                                 }
232                             });
233                             
234                             String prevUser = null;
235                             boolean userOK=true;
236                             for (Approval appr : currApproverList) {
237                                 if (++line<MAX_LINE) { // limit number displayed at one time.
238                                     AbsCell userCell;
239                                     String user = appr.getUser();
240                                     
241                                     if (user.equals(prevUser)) {
242                                         userCell = AbsCell.Null; 
243                                     } else if (user.endsWith(trans.org().getRealm())){
244                                         userOK=true;
245 //                                      String title;
246                                         Organization org = OrganizationFactory.obtain(trans.env(), user);
247                                         if (org==null) {
248 //                                          title="";
249                                                 userCell = new TextCell(user);
250                                         } else {
251                                             Identity au = org.getIdentity(trans, user);
252                                             if (au!=null) {
253                                                 if(au.isPerson()) {
254                                                         userCell = new TextCell(au.fullName() + "\n(" + au.id() + ')');
255                                                 } else {
256                                                         userCell = new TextCell(au.fullID());
257                                                 }
258 //                                              
259 //                                              if ("MECHID".equals(au.type())) {
260 //                                                  Identity managedBy = au.responsibleTo();
261 //                                                  if (managedBy==null) {
262 //                                                      title ="title=" + au.type();
263 //                                                  } else {
264 //                                                      title="title=Sponsor is " + managedBy.fullName();                                                
265 //                                                  }
266 //                                              } else {
267 //                                                  title="title=" + au.fullName();
268 //                                              }
269                                             } else {
270                                                 userOK=false;
271 //                                              title="title=Not a User at " + org.getName();
272                                                         userCell = new TextCell(user);
273                                             }
274                                         }
275                                         prevUser=user;
276         //                                userCell = new RefCell(prevUser,
277         //                                    TODO_ILM_INFO+user.substring(0, user.length()-domainOfApprover.length()),
278         //                                    true,
279         //                                    title);
280                                         
281                                     } else {
282                                         userCell = new TextCell(prevUser==null?user:prevUser);
283                                     }
284                                     AbsCell[] sa = new AbsCell[] {
285                                         userCell,
286                                         new TextCell(appr.getMemo()),
287                                         userOK?new RadioCell("line."+ line,"approve", "approved|"+appr.getTicket()):new TextCell(""),
288                                         new RadioCell("line."+ line,"deny", "denied|"+appr.getTicket())
289                                     };
290                                     rv.add(sa);
291                                 } else {
292                                     ++numLeft;
293                                 }
294                             }
295                         }
296                         if (numLeft>0) {
297                             msg = "After these, there will be " + numLeft + " approvals left to process";
298                         }
299                         if (rv.isEmpty()) {
300                             if (numLeft>0) {
301                                 msg = "No Approvals to process at this time for user " + userParam +". You have " 
302                                     + numLeft + " other approvals to process.";
303                             } else {
304                                 msg = "No Approvals to process at this time";
305                             }
306                         }
307                 }
308             } catch (Exception e) {
309                 trans.error().log(e);
310             } finally {
311                 tt.done();
312             }
313         return new Cells(rv,msg);
314         }
315     }
316 }