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.gui.pages;
24 import java.io.IOException;
25 import java.io.StringWriter;
26 import java.net.ConnectException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Comparator;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.List;
34 import java.util.Map.Entry;
37 import javax.xml.datatype.XMLGregorianCalendar;
39 import org.onap.aaf.auth.cmd.AAFcli;
40 import org.onap.aaf.auth.env.AuthzTrans;
41 import org.onap.aaf.auth.gui.AAF_GUI;
42 import org.onap.aaf.auth.gui.BreadCrumbs;
43 import org.onap.aaf.auth.gui.Page;
44 import org.onap.aaf.auth.gui.SlotCode;
45 import org.onap.aaf.auth.gui.Table;
46 import org.onap.aaf.auth.gui.Table.Cells;
47 import org.onap.aaf.auth.gui.table.AbsCell;
48 import org.onap.aaf.auth.gui.table.TableData;
49 import org.onap.aaf.auth.gui.table.TextCell;
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.cadi.util.FQI;
55 import org.onap.aaf.misc.env.APIException;
56 import org.onap.aaf.misc.env.Env;
57 import org.onap.aaf.misc.env.TimeTaken;
58 import org.onap.aaf.misc.env.util.Chrono;
59 import org.onap.aaf.misc.xgen.Cache;
60 import org.onap.aaf.misc.xgen.DynamicCode;
61 import org.onap.aaf.misc.xgen.Mark;
62 import org.onap.aaf.misc.xgen.html.HTMLGen;
64 import aaf.v2_0.Users;
65 import aaf.v2_0.Users.User;
66 import certman.v1_0.Artifacts;
67 import certman.v1_0.Artifacts.Artifact;
69 public class CredDetail extends Page {
71 public static final String HREF = "/gui/creddetail";
72 public static final String NAME = "CredDetail";
73 private static Model model;
74 private static SlotCode<AuthzTrans> slotCode;
78 public CredDetail(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
79 super(gui.env, NAME, HREF, Params.values(),
80 new BreadCrumbs(breadcrumbs),
81 new Table<AAF_GUI,AuthzTrans>("Cred Details",gui.env.newTransNoAvg(),model = new Model(),
82 slotCode = new SlotCode<AuthzTrans>(false,gui.env,NAME,Params.values()) {
84 public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
85 cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
87 public void code(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
88 String ns = get(trans, Params.ns,"");
89 String domain = FQI.reverseDomain(ns);
90 Mark js = new Mark(), fn=new Mark();
91 hgen.js(js).function(fn,"newArtifact")
92 .text("id=document.getElementById('id');")
93 .text("if (id.value=='') {alert('Enter the id in box');} else {")
94 .text("window.open('"+CMArtiChangeForm.HREF+"?id='+id.value+'&ns="+ns+"','_self');}"
97 .function("newPassword")
98 .text("id=document.getElementById('id');")
99 .text("if (id.value=='') {alert('Enter the id in box');} else {")
100 .text("window.open('"+PassChangeForm.HREF+"?id='+id.value+'@"+domain+"&ns="+ns+"','_self');}"
103 hgen.leaf("i","style=margin:1em 0em 1em 1em;").text("ID:").end()
104 .leaf("input","id=id","style=width:10%;").end().text("@").text(domain).br()
105 .leaf(HTMLGen.A,"class=greenbutton","href=javascript:newArtifact()","style=color:white;margin:1.2em 0em 1em 1em;").text("As Cert Artifact").end()
106 .leaf(HTMLGen.A,"class=greenbutton","href=javascript:newPassword()","style=color:white;margin:1.2em 0em 1em 1em;").text("w/Password").end()
114 // Setting so we can get access to HTMLGen clone
115 model.set(this,slotCode);
121 * Implement the table content for Cred Detail
126 private static class Model extends TableData<AAF_GUI,AuthzTrans> {
127 private static final String STYLE_WIDTH_5 = "style=width:5%;";
128 private static final String STYLE_WIDTH_10 = "style=width:10%;";
129 private static final String STYLE_WIDTH_15 = "style=width:15%;";
130 private static final String STYLE_WIDTH_20 = "style=width:20%;";
131 private static final String STYLE_WIDTH_70 = "style=width:70%;";
132 private SlotCode<AuthzTrans> sc;
133 private CredDetail cd;
134 // Covering for Constructor Order
135 private void set(CredDetail credDetail, SlotCode<AuthzTrans> slotCode) {
141 public void prefix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
145 public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
146 final String ns = sc.get(trans, Params.ns, "");
147 final String id = sc.get(trans, Params.id, "");
151 final ArrayList<AbsCell[]> rv = new ArrayList<>();
152 final TimeTaken tt = trans.start("AAF Cred Details",Env.REMOTE);
155 la = gui.cmClientAsUser(trans.getUserPrincipal(), new Retryable<List<Artifact>>() {
157 public List<Artifact> code(Rcli<?> client)throws CadiException, ConnectException, APIException {
158 Future<Artifacts> fa = client.read("/cert/artifacts?ns="+ns,gui.artifactsDF);
159 if (fa.get(AAFcli.timeout())) {
160 return fa.value.getArtifact();
167 final Set<String> lns = new HashSet<>();
169 for (Artifact a : la){
170 lns.add(a.getMechid());
173 gui.clientAsUser(trans.getUserPrincipal(),new Retryable<Void>() {
175 public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
176 Future<Users> fu = client.read("/authn/creds/ns/"+ns,gui.getDF(Users.class));
177 if (fu.get(AAFcli.timeout())) {
178 // Organize User entries
179 Map<String,List<Map<Integer,List<User>>>> users = new HashMap<>();
181 List<Map<Integer,List<User>>> lmu=null;
182 Map<Integer, List<User>> mu = null;
183 List<User> lu = null;
185 for (User u : fu.value.getUser()) {
186 if (u.getType() == 200) {
187 lns.remove(u.getId());
189 lmu = users.get(u.getId());
191 users.put(u.getId(),lmu=new ArrayList<>());
194 for (Map<Integer,List<User>> xmu : lmu) {
195 if (xmu.containsKey(u.getType())) {
201 lmu.add(mu=new HashMap<>());
204 lu = mu.get(u.getType());
206 mu.put(u.getType(),lu = new ArrayList<>());
212 for (Entry<String, List<Map<Integer, List<User>>>> ulm : users.entrySet()) {
213 String key = "cred_"+count++;
214 StringWriter buttons = new StringWriter();
215 HTMLGen hgen = cd.clone(buttons);
216 hgen.leaf("button","onclick=divVisibility('"+key+"');","class=button").text("Expand").end();
218 StringWriter creds = new StringWriter();
219 hgen = cd.clone(creds);
220 Mark div = hgen.divID(key,ulm.getKey().equals(id)?"":"style=display:none;");
221 for (Map<Integer, List<User>> miu : ulm.getValue()) {
222 Mark utable = new Mark();
223 hgen.leaf(utable,HTMLGen.TABLE);
225 Mark uRow = new Mark();
227 boolean first = true;
229 for ( Entry<Integer, List<User>> es : miu.entrySet()) {
230 Collections.sort(es.getValue(),new Comparator<User>() {
232 public int compare(User u1, User u2) {
233 int rv = u1.getType().compareTo(u2.getType());
234 return rv==0?u2.getExpires().compare(u1.getExpires()):rv;
238 XMLGregorianCalendar oldest=null, newest=null;
240 for (User u: es.getValue()) {
244 // Need to compile entries for Certificates on this screen
245 if (es.getKey()==200) {
247 if (oldest==null || oldest.compare(u.getExpires())<0) {
248 oldest = u.getExpires();
250 if (newest==null || newest.compare(u.getExpires())<0) {
251 newest = u.getExpires();
254 hgen.leaf(uRow,HTMLGen.TR);
256 hgen.leaf(HTMLGen.TD,cls="class=detailFirst",STYLE_WIDTH_10);
257 switch(es.getKey()) {
259 case 2: hgen.text("Password");
261 case 10: hgen.text("Certificate"); break;
264 hgen.leaf(HTMLGen.TD,cls="class=detail",STYLE_WIDTH_10+"text-align:center;").text("\"");
267 hgen.incr(HTMLGen.TD,cls,STYLE_WIDTH_20);
271 "href="+PassDeleteAction.HREF+
274 "&date="+u.getExpires().toXMLFormat() +
275 "&type="+u.getType())
276 .text("Delete").end();
277 if (first && es.getKey()<10) { // Change Password Screen
278 hgen.leaf(HTMLGen.A,"class=button","href="+PassChangeForm.HREF+"?id="+id+"&ns="+ns)
283 hgen.end().leaf(HTMLGen.TD,cls,STYLE_WIDTH_70)
284 .text(Chrono.niceDateStamp(u.getExpires()))
290 if (xcnt>0) { // print compilations, if any, of Certificate
291 hgen.leaf(uRow,HTMLGen.TR)
292 .leaf(HTMLGen.TD,cls="class=detailFirst",STYLE_WIDTH_10).text("x509").end()
293 .leaf(HTMLGen.TD, cls,STYLE_WIDTH_20)
294 .leaf(HTMLGen.A,"class=button","href="+CMArtifactShow.HREF+"?id="+id+"&ns="+ns)
297 .leaf(HTMLGen.TD, cls,STYLE_WIDTH_70).text(String.format(
298 xcnt>0?"%d Certificate%s, ranging from %s to %s"
302 Chrono.niceDateStamp(oldest),
303 Chrono.niceDateStamp(newest)))
313 rv.add(new AbsCell[] {
314 new TextCell(ulm.getKey(),STYLE_WIDTH_15),
315 new TextCell(buttons.toString(),STYLE_WIDTH_5),
316 new TextCell(creds.toString(),STYLE_WIDTH_70)
319 for (String missing : lns) {
320 StringWriter buttons = new StringWriter();
321 HTMLGen hgen = cd.clone(buttons);
322 hgen.leaf(HTMLGen.A,"class=button","href="+CMArtifactShow.HREF+"?id="+missing+"&ns="+ns)
325 rv.add(new AbsCell[] {
326 new TextCell(missing,STYLE_WIDTH_15),
327 new TextCell(buttons.toString(),STYLE_WIDTH_5),
328 new TextCell("No X509 Credential Instantiated")
333 rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***")});
338 } catch (Exception e) {
343 return new Cells(rv,null);
347 public void postfix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {