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