summaryrefslogtreecommitdiffstats
path: root/auth/auth-gui/src
diff options
context:
space:
mode:
authorInstrumental <jcgmisc@stl.gathman.org>2018-03-26 13:51:48 -0700
committerInstrumental <jcgmisc@stl.gathman.org>2018-03-26 13:52:07 -0700
commit71037c39a37d3549dcfe31926832a657744fbe05 (patch)
tree78911b2b5e86e4e44228f7a27b3a8cd954b7f3e2 /auth/auth-gui/src
parenta20accc73189d8e5454cd26049c0e6fae75da16f (diff)
AT&T 2.0.19 Code drop, stage 3
Issue-ID: AAF-197 Change-Id: I8b02cb073ccba318ccaf6ea0276446bdce88fb82 Signed-off-by: Instrumental <jcgmisc@stl.gathman.org>
Diffstat (limited to 'auth/auth-gui/src')
-rw-r--r--auth/auth-gui/src/main/config/.gitignore2
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java93
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java267
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/BreadCrumbs.java90
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/ContentCode.java36
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Controls.java45
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Display.java140
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Form.java68
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/NamedCode.java67
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/OrgLookupFilter.java58
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java402
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/SlotCode.java49
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Table.java229
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/XFrameFilter.java73
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java334
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiExample.java133
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalAction.java121
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalForm.java299
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java219
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeForm.java256
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java251
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java352
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java77
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLanding.java115
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLandingAction.java65
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java247
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java230
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoAction.java158
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoForm.java162
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NssShow.java142
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeAction.java211
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeForm.java205
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassDeleteAction.java88
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java193
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java160
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantAction.java135
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantForm.java157
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java243
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermsShow.java121
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RequestDetail.java190
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java295
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetailAction.java188
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java228
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RolesShow.java144
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleExtend.java99
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleRemove.java97
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/WebCommand.java118
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/AbsCell.java48
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/ButtonCell.java45
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/CheckBoxCell.java66
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RadioCell.java48
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RefCell.java54
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TableData.java56
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextAndRefCell.java43
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextCell.java49
-rw-r--r--auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextInputCell.java54
56 files changed, 8115 insertions, 0 deletions
diff --git a/auth/auth-gui/src/main/config/.gitignore b/auth/auth-gui/src/main/config/.gitignore
new file mode 100644
index 00000000..04cdc540
--- /dev/null
+++ b/auth/auth-gui/src/main/config/.gitignore
@@ -0,0 +1,2 @@
+/authGUI.props
+/log4j.properties
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java
new file mode 100644
index 00000000..29e36505
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java
@@ -0,0 +1,93 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cui;
+
+import java.io.PrintWriter;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.rserv.HttpCode;
+import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp;
+import org.onap.aaf.cadi.http.HTransferSS;
+import org.onap.aaf.cadi.principal.TaggedPrincipal;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+
+public class CUI extends HttpCode<AuthzTrans, Void> {
+ private final AAF_GUI gui;
+ public CUI(AAF_GUI gui) {
+ super(null,"Command Line");
+ this.gui = gui;
+ }
+
+ @Override
+ public void handle(AuthzTrans trans, HttpServletRequest req,HttpServletResponse resp) throws Exception {
+ ServletInputStream isr = req.getInputStream();
+ PrintWriter pw = resp.getWriter();
+ int c;
+ StringBuilder cmd = new StringBuilder();
+
+ while((c=isr.read())>=0) {
+ cmd.append((char)c);
+ }
+
+ TimeTaken tt = trans.start("Execute AAFCLI", Env.REMOTE);
+ try {
+ TaggedPrincipal p = trans.getUserPrincipal();
+ // Access needs to be set after overall construction. Thus, the lazy create.
+ AAFcli aafcli;
+ AAFConHttp aafcon = gui.aafCon();
+ aafcli= new AAFcli(gui.access,gui.env, pw,
+ aafcon.hman(),
+ aafcon.securityInfo(),
+ new HTransferSS(p,AAF_GUI.app,
+ aafcon.securityInfo()));
+ aafcli.verbose(false);
+ aafcli.gui(true);
+
+ String cmdStr = cmd.toString();
+ if (!cmdStr.contains("--help")) {
+ cmdStr = cmdStr.replaceAll("help", "--help");
+ }
+ if (!cmdStr.contains("--version")) {
+ cmdStr = cmdStr.replaceAll("version", "--version");
+ }
+ try {
+ aafcli.eval(cmdStr);
+ pw.flush();
+ } catch (Exception e) {
+ pw.flush();
+ pw.println(e.getMessage());
+ } finally {
+ aafcli.close();
+ }
+ } finally {
+ tt.done();
+ }
+
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java
new file mode 100644
index 00000000..be93d63c
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java
@@ -0,0 +1,267 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import static org.onap.aaf.auth.rserv.HttpMethods.GET;
+import static org.onap.aaf.auth.rserv.HttpMethods.POST;
+import static org.onap.aaf.auth.rserv.HttpMethods.PUT;
+
+import javax.servlet.Filter;
+
+import org.onap.aaf.auth.cmd.Cmd;
+import org.onap.aaf.auth.cui.CUI;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.env.AuthzTransFilter;
+import org.onap.aaf.auth.gui.pages.ApiDocs;
+import org.onap.aaf.auth.gui.pages.ApiExample;
+import org.onap.aaf.auth.gui.pages.ApprovalAction;
+import org.onap.aaf.auth.gui.pages.ApprovalForm;
+import org.onap.aaf.auth.gui.pages.CMArtiChangeAction;
+import org.onap.aaf.auth.gui.pages.CMArtiChangeForm;
+import org.onap.aaf.auth.gui.pages.CMArtifactShow;
+import org.onap.aaf.auth.gui.pages.CredDetail;
+import org.onap.aaf.auth.gui.pages.Home;
+import org.onap.aaf.auth.gui.pages.LoginLanding;
+import org.onap.aaf.auth.gui.pages.LoginLandingAction;
+import org.onap.aaf.auth.gui.pages.NsDetail;
+import org.onap.aaf.auth.gui.pages.NsHistory;
+import org.onap.aaf.auth.gui.pages.NsInfoAction;
+import org.onap.aaf.auth.gui.pages.NsInfoForm;
+import org.onap.aaf.auth.gui.pages.NssShow;
+import org.onap.aaf.auth.gui.pages.PassChangeAction;
+import org.onap.aaf.auth.gui.pages.PassChangeForm;
+import org.onap.aaf.auth.gui.pages.PassDeleteAction;
+import org.onap.aaf.auth.gui.pages.PendingRequestsShow;
+import org.onap.aaf.auth.gui.pages.PermDetail;
+import org.onap.aaf.auth.gui.pages.PermGrantAction;
+import org.onap.aaf.auth.gui.pages.PermGrantForm;
+import org.onap.aaf.auth.gui.pages.PermHistory;
+import org.onap.aaf.auth.gui.pages.PermsShow;
+import org.onap.aaf.auth.gui.pages.RequestDetail;
+import org.onap.aaf.auth.gui.pages.RoleDetail;
+import org.onap.aaf.auth.gui.pages.RoleDetailAction;
+import org.onap.aaf.auth.gui.pages.RoleHistory;
+import org.onap.aaf.auth.gui.pages.RolesShow;
+import org.onap.aaf.auth.gui.pages.UserRoleExtend;
+import org.onap.aaf.auth.gui.pages.UserRoleRemove;
+import org.onap.aaf.auth.gui.pages.WebCommand;
+import org.onap.aaf.auth.rserv.CachingFileAccess;
+import org.onap.aaf.auth.server.AbsService;
+import org.onap.aaf.auth.server.JettyServiceStarter;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp;
+import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;
+import org.onap.aaf.cadi.aaf.v2_0.AAFTrustChecker;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.http.HTransferSS;
+import org.onap.aaf.cadi.principal.TaggedPrincipal;
+import org.onap.aaf.cadi.register.Registrant;
+import org.onap.aaf.cadi.register.RemoteRegistrant;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.StaticSlot;
+import org.onap.aaf.misc.env.util.Split;
+import org.onap.aaf.misc.rosetta.env.RosettaDF;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+import org.onap.aaf.misc.xgen.html.State;
+
+import certman.v1_0.Artifacts;
+import certman.v1_0.CertInfo;
+
+public class AAF_GUI extends AbsService<AuthzEnv, AuthzTrans> implements State<Env>{
+ private static final String AAF_GUI_THEME = "aaf_gui_theme";
+ public static final String AAF_GUI_COPYRIGHT = "aaf_gui_copyright";
+ public static final String HTTP_SERVLET_REQUEST = "HTTP_SERVLET_REQUEST";
+ public static final int TIMEOUT = 60000;
+ public static final String app = "AAF GUI";
+
+ // AAF API
+
+ // Certificate manager API
+ public RosettaDF<Artifacts> artifactsDF;
+ public RosettaDF<CertInfo> certInfoDF;
+
+ private final AAFConHttp cmCon;
+ public final AAFConHttp aafCon;
+ public final AAFLurPerm lur;
+
+ public final Slot slot_httpServletRequest;
+ protected final String deployedVersion;
+ private StaticSlot sTheme;
+ public final String theme;
+
+
+ public AAF_GUI(final AuthzEnv env) throws Exception {
+ super(env.access(), env);
+ sTheme = env.staticSlot(CachingFileAccess.CFA_WEB_PATH,access.getProperty(CachingFileAccess.CFA_WEB_PATH,null)==null?AAF_GUI_THEME:CachingFileAccess.CFA_WEB_PATH);
+ theme = env.getProperty(AAF_GUI_THEME);
+
+ //OrganizationFactory.setDefaultOrg(env, "org.osaaf.authz.org.att.ATT");
+
+ slot_httpServletRequest = env.slot(HTTP_SERVLET_REQUEST);
+ String[] component = Split.split(':', access.getProperty(Config.AAF_COMPONENT, "N/A:2.x"));
+ if(component.length>1) {
+ deployedVersion =component[1];
+ } else {
+ deployedVersion = "2.x";
+ }
+
+ // Certificate Manager
+ cmCon = new AAFConHttp(env.access(),Config.CM_URL);
+ artifactsDF = env.newDataFactory(Artifacts.class);
+ certInfoDF = env.newDataFactory(CertInfo.class);
+
+
+ /////////////////////////
+ // Screens
+ /////////////////////////
+ // Start Screen
+ final Page start = new Display(this, GET, new Home(this)).page();
+
+ // MyPerms Screens
+ final Page myPerms = new Display(this, GET, new PermsShow(this, start)).page();
+ Page permDetail = new Display(this, GET, new PermDetail(this, start, myPerms)).page();
+ new Display(this, GET, new PermHistory(this,start,myPerms,permDetail));
+
+ // MyRoles Screens
+ final Page myRoles = new Display(this, GET, new RolesShow(this, start)).page();
+ Page roleDetail = new Display(this, GET, new RoleDetail(this, start, myRoles)).page();
+ new Display(this, POST, new RoleDetailAction(this,start,myRoles,roleDetail));
+ new Display(this, GET, new RoleHistory(this,start,myRoles,roleDetail));
+
+ // MyNameSpace
+ final Page myNamespaces = new Display(this, GET, new NssShow(this, start)).page();
+ Page nsDetail = new Display(this, GET, new NsDetail(this, start, myNamespaces)).page();
+ new Display(this, GET, new NsHistory(this, start,myNamespaces,nsDetail));
+ Page crdDetail = new Display(this, GET, new CredDetail(this, start, myNamespaces, nsDetail)).page();
+ Page artiShow = new Display(this, GET, new CMArtifactShow(this, start, myNamespaces, nsDetail, crdDetail)).page();
+ Page artiCForm = new Display(this, GET, new CMArtiChangeForm(this, start, myNamespaces, nsDetail, crdDetail,artiShow)).page();
+ new Display(this, POST, new CMArtiChangeAction(this, start,artiShow,artiCForm));
+
+ // Password Change Screens
+ final Page pwc = new Display(this, GET, new PassChangeForm(this, start,crdDetail)).page();
+ new Display(this, POST, new PassChangeAction(this, start, pwc));
+
+ // Password Delete Screen
+ new Display(this, GET, new PassDeleteAction(this, start,crdDetail));
+
+ // Validation Change Screens
+ final Page validate = new Display(this, GET, new ApprovalForm(this, start)).page();
+ new Display(this, POST, new ApprovalAction(this, start, validate));
+
+ // Onboard, Detailed Edit Screens
+ final Page onb = new Display(this, GET, new NsInfoForm(this, start)).page();
+ new Display(this, POST, new NsInfoAction(this, start, onb));
+
+ // Web Command Screens
+ /* final Page webCommand =*/ new Display(this, GET, new WebCommand(this, start)).page();
+
+ // API Docs
+ final Page apidocs = new Display(this, GET, new ApiDocs(this, start)).page();
+ new Display(this, GET, new ApiExample(this,start, apidocs)).page();
+
+ // Permission Grant Page
+ final Page permGrant = new Display(this, GET, new PermGrantForm(this, start)).page();
+ new Display(this, POST, new PermGrantAction(this, start, permGrant)).page();
+
+ // Login Landing if no credentials detected
+ final Page loginLanding = new Display(this, GET, new LoginLanding(this, start)).page();
+ new Display(this, POST, new LoginLandingAction(this, start, loginLanding));
+
+ // User Role Request Extend and Remove
+ new Display(this, GET, new UserRoleExtend(this, start,myRoles)).page();
+ new Display(this, GET, new UserRoleRemove(this, start,myRoles)).page();
+
+ // See my Pending Requests
+ final Page requestsShow = new Display(this, GET, new PendingRequestsShow(this, start)).page();
+ new Display(this, GET, new RequestDetail(this, start, requestsShow));
+
+ // Command line Mechanism
+ route(env, PUT, "/gui/cui", new CUI(this),"text/plain;charset=utf-8","*/*");
+
+ ///////////////////////
+ // WebContent Handler
+ ///////////////////////
+ route(env,GET,"/"+env.get(sTheme)+"/:key", new CachingFileAccess<AuthzTrans>(env));
+ ///////////////////////
+ aafCon = aafCon();
+ lur = aafCon.newLur();
+ }
+
+ public<T> RosettaDF<T> getDF(Class<T> cls) throws APIException {
+ return Cmd.getDF(env,cls);
+ }
+
+ public void writeError(AuthzTrans trans, Future<?> fp, HTMLGen hgen, int indent) {
+ if(hgen!=null) {
+ String msg = aafCon.readableErrMsg(fp);
+ hgen.incr(HTMLGen.P,"style=text-indent:"+indent*10+"px")
+ .text("<font color=\"red\"><i>Error</i>:</font> ")
+ .text(msg)
+ .end();
+ trans.checkpoint(msg);
+ }
+ }
+
+ public<RET> RET cmClientAsUser(TaggedPrincipal p,Retryable<RET> retryable) throws APIException, LocatorException, CadiException {
+ return cmCon.hman().best(new HTransferSS(p,app, aafCon.securityInfo()), retryable);
+ }
+ @Override
+ public Filter[] filters() throws CadiException, LocatorException {
+ try {
+ return new Filter[] {
+ new XFrameFilter(XFrameFilter.TYPE.none),
+ new AuthzTransFilter(env,aafCon(),
+ new AAFTrustChecker((Env)env)),
+ new OrgLookupFilter()
+ };
+ } catch (NumberFormatException e) {
+ throw new CadiException("Invalid Property information", e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Registrant<AuthzEnv>[] registrants(final int port) throws CadiException, LocatorException {
+ return new Registrant[] {
+ new RemoteRegistrant<AuthzEnv>(aafCon(),app_name,app_version,port)
+ };
+ }
+
+ public static void main(final String[] args) {
+ PropAccess propAccess = new PropAccess(args);
+ try {
+ AAF_GUI service = new AAF_GUI(new AuthzEnv(propAccess));
+// env.setLog4JNames("log4j.properties","authz","gui","audit","init","trace ");
+ JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service);
+ jss.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/BreadCrumbs.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/BreadCrumbs.java
new file mode 100644
index 00000000..4602184f
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/BreadCrumbs.java
@@ -0,0 +1,90 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.A;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.LI;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.UL;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.TransStore;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class BreadCrumbs extends NamedCode {
+ private Page[] breadcrumbs;
+
+ public BreadCrumbs(Page ... pages) {
+ super(false,"breadcrumbs");
+ breadcrumbs = pages;
+ }
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ // BreadCrumbs
+ Mark mark = new Mark();
+ hgen.incr(mark, UL);
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, TransStore>() {
+ @Override
+ public void code(AAF_GUI gui, TransStore trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ HttpServletRequest req = trans.get(gui.slot_httpServletRequest, null);
+ StringBuilder key = new StringBuilder();
+ String value, hidden;
+ for(Page p : breadcrumbs) {
+ hidden="";
+ // Add keys for page from commandline, where possible.
+ if(p.fields().length>0) {
+ boolean first = true;
+ key.setLength(0);
+ for(String field : p.fields()) {
+ if((value=req.getParameter(field))==null) {
+ hidden="style=display:none;";
+ break;
+ }
+ if(first) {
+ first = false;
+ key.append('?');
+ } else {
+ key.append("&amp;");
+ }
+ key.append(field);
+ key.append('=');
+ key.append(value);
+ }
+ hgen.incr(LI,true,hidden);
+ hgen.leaf(A,"href="+p.url()+key.toString(),hidden).text(p.name()).end(2);
+ } else {
+ hgen.incr(LI,true);
+ hgen.leaf(A,"href="+p.url(),hidden).text(p.name()).end(2);
+ }
+ }
+ }
+ });
+ hgen.end(mark);
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/ContentCode.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/ContentCode.java
new file mode 100644
index 00000000..d3c24dc2
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/ContentCode.java
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import org.onap.aaf.misc.xgen.Code;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+/**
+ * Interface for which Page, etc can get Attributes, determine whether cached, etc
+ * @author Jonathan
+ *
+ */
+public interface ContentCode extends Code<HTMLGen> {
+ public String[] idattrs();
+ public void addAttr(boolean first, String attr);
+ public boolean no_cache();
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Controls.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Controls.java
new file mode 100644
index 00000000..5b582f38
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Controls.java
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import java.io.IOException;
+
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class Controls extends NamedCode {
+ public Controls() {
+ super(false,"controls");
+ }
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ hgen.incr("form","method=post")
+ .incr("input", true, "type=checkbox", "name=vehicle", "value=Bike").text("I have a bike").end()
+ .text("Password: ")
+ .incr("input", true, "type=password", "id=password1").end()
+ .tagOnly("input", "type=submit", "value=Submit")
+ .end();
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Display.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Display.java
new file mode 100644
index 00000000..ad43d3fb
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Display.java
@@ -0,0 +1,140 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.rserv.HttpCode;
+import org.onap.aaf.auth.rserv.HttpMethods;
+import org.onap.aaf.misc.env.Slot;
+
+public class Display {
+ private final Page get;
+ public Display(final AAF_GUI gui, final HttpMethods meth, final Page page) {
+ get = page;
+ final String[] fields = page.fields();
+ final Slot slots[] = new Slot[fields.length];
+ String prefix = page.name() + '.';
+ for(int i=0;i<slots.length;++i) {
+ slots[i] = gui.env.slot(prefix + fields[i]);
+ }
+
+ /*
+ * We handle all the "Form POST" calls here with a naming convention that allows us to create arrays from strings.
+ *
+ * On the HTTP side, elements concatenate their name with their Index number (if multiple). In this code,
+ * we turn such names into arrays with same index number. Then, we place them in the Transaction "Properties" so that
+ * it can be transferred to subclasses easily.
+ */
+ if(meth.equals(HttpMethods.POST)) {
+ // Here, we'll expect FORM URL Encoded Data, which we need to get from the body
+ gui.route(gui.env, meth, page.url(),
+ new HttpCode<AuthzTrans,AAF_GUI>(gui,page.name()) {
+ @Override
+ public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+ trans.put(gui.slot_httpServletRequest, req);
+ for(int i=0; i<fields.length;++i) {
+ int idx = fields[i].indexOf("[]");
+ if(idx<0) { // single value
+ trans.put(slots[i], req.getParameter(fields[i])); // assume first value
+ } else { // multi value - Expect Values to be set with Field root name "field.<int>" corresponding to an array of types
+ String field=fields[i].substring(0, idx)+'.';
+ String[] array = new String[16];
+ for(Enumeration<String> names = req.getParameterNames(); names.hasMoreElements();) {
+ String key = names.nextElement();
+ if(key.startsWith(field)) {
+ try {
+ int x = Integer.parseInt(key.substring(field.length()));
+ if(x>=array.length) {
+ String[] temp = new String[x+10];
+ System.arraycopy(temp, 0, temp, 0, array.length);
+ array = temp;
+ }
+ array[x]=req.getParameter(key);
+ } catch (NumberFormatException e) {
+ trans.debug().log(e);
+ }
+ }
+ }
+ trans.put(slots[i], array);
+ }
+ }
+ page.replay(context,trans,resp.getOutputStream(),"general");
+ }
+ }, "application/x-www-form-urlencoded","*/*");
+
+ } else {
+ // Transfer whether Page shouldn't be cached to local Final var.
+ final boolean no_cache = page.no_cache;
+
+ gui.route(gui.env, meth, page.url(),
+ new HttpCode<AuthzTrans,AAF_GUI>(gui,page.name()) {
+ @Override
+ public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+ trans.put(gui.slot_httpServletRequest, req);
+ for(int i=0; i<slots.length;++i) {
+ int idx = fields[i].indexOf("[]");
+ if(idx<0) { // single value
+ trans.put(slots[i], req.getParameter(fields[i]));
+ } else { // multi value
+ String[] array = new String[30];
+ String field=fields[i].substring(0, idx);
+
+ for(Enumeration<String> mm = req.getParameterNames();mm.hasMoreElements();) {
+ String key = mm.nextElement();
+ if(key.startsWith(field)) {
+ try {
+ int x = Integer.parseInt(key.substring(field.length()));
+ if(x>=array.length) {
+ String[] temp = new String[x+10];
+ System.arraycopy(temp, 0, temp, 0, array.length);
+ array = temp;
+ }
+ array[x]=req.getParameter(key);
+ } catch (NumberFormatException e) {
+ trans.debug().log(e);
+ }
+ }
+ }
+ trans.put(slots[i], array);
+ }
+ }
+ page.replay(context,trans,resp.getOutputStream(),"general");
+ }
+
+ @Override
+ public boolean no_cache() {
+ return no_cache;
+ }
+ }, "text/html","*/*");
+ }
+
+ }
+
+ public Page page() {
+ return get;
+ }
+} \ No newline at end of file
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Form.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Form.java
new file mode 100644
index 00000000..7011395c
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Form.java
@@ -0,0 +1,68 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import java.io.IOException;
+
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class Form extends NamedCode {
+ private String preamble;
+ private NamedCode content;
+
+ public Form(boolean no_cache, NamedCode content) {
+ super(no_cache,content);
+ this.content = content;
+ preamble=null;
+ }
+
+ public Form preamble(String preamble) {
+ this.preamble = preamble;
+ return this;
+ }
+
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ if(preamble!=null) {
+ hgen.incr("p","class=preamble").text(preamble).end();
+ }
+ hgen.incr("form","method=post");
+
+ content.code(cache, hgen);
+
+ hgen.tagOnly("input", "type=submit", "value=Submit")
+ .tagOnly("input", "type=reset", "value=Reset")
+ .end();
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aaf.auth.gui.NamedCode#idattrs()
+ */
+ @Override
+ public String[] idattrs() {
+ return content.idattrs();
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/NamedCode.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/NamedCode.java
new file mode 100644
index 00000000..e4bd6c7d
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/NamedCode.java
@@ -0,0 +1,67 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+public abstract class NamedCode implements ContentCode {
+ private final boolean no_cache;
+ private String name;
+ private String[] idattrs;
+
+ /*
+ * Mark whether this code should not be cached, and any attributes
+ */
+ public NamedCode(final boolean no_cache, final String name) {
+ this.name = name;
+ idattrs = new String[] {name};
+ this.no_cache = no_cache;
+ }
+
+ public NamedCode(boolean no_cache, NamedCode content) {
+ this.no_cache = no_cache;
+ name=content.name;
+ idattrs = content.idattrs;
+ }
+
+ /**
+ * Return ID and Any Attributes needed to create a "div" section of this code
+ * @return
+ */
+ public String[] idattrs() {
+ return idattrs;
+ }
+
+ public void addAttr(boolean first, String attr) {
+ String[] temp = new String[idattrs.length+1];
+ if(first) {
+ temp[0] = attr;
+ System.arraycopy(idattrs, 0, temp, 1, idattrs.length);
+ } else {
+ temp[idattrs.length] = attr;
+ System.arraycopy(idattrs, 0, temp, 0, idattrs.length);
+ }
+ idattrs = temp;
+ }
+
+ public boolean no_cache() {
+ return no_cache;
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/OrgLookupFilter.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/OrgLookupFilter.java
new file mode 100644
index 00000000..411ecdb8
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/OrgLookupFilter.java
@@ -0,0 +1,58 @@
+package org.onap.aaf.auth.gui;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.auth.org.Organization.Identity;
+import org.onap.aaf.auth.rserv.TransFilter;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.principal.TaggedPrincipal;
+
+public class OrgLookupFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) throws IOException, ServletException {
+ final AuthzTrans trans = (AuthzTrans) req.getAttribute(TransFilter.TRANS_TAG);
+ if(req instanceof HttpServletRequest) {
+ Principal p = ((HttpServletRequest)req).getUserPrincipal();
+ if(p instanceof TaggedPrincipal) {
+ ((TaggedPrincipal)p).setTagLookup(new TaggedPrincipal.TagLookup() {
+ @Override
+ public String lookup() throws CadiException {
+ Identity id;
+ try {
+ id = trans.org().getIdentity(trans, p.getName());
+ if(id.isFound()) {
+ return id.firstName();
+ }
+ } catch (OrganizationException e) {
+ throw new CadiException(e);
+ }
+ return p.getName();
+ }
+ });
+ }
+ fc.doFilter(req, resp);
+ }
+
+ }
+
+
+ @Override
+ public void destroy() {
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java
new file mode 100644
index 00000000..436b37a0
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java
@@ -0,0 +1,402 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.A;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.H1;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.LI;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TITLE;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.UL;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.aaf.auth.common.Define;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.rserv.CachingFileAccess;
+import org.onap.aaf.cadi.Permission;
+import org.onap.aaf.cadi.aaf.AAFPermission;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.principal.TaggedPrincipal;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.StaticSlot;
+import org.onap.aaf.misc.env.util.Split;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.CacheGen;
+import org.onap.aaf.misc.xgen.Code;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLCacheGen;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+import org.onap.aaf.misc.xgen.html.Imports;
+
+/**
+ * A Base "Mobile First" Page
+ *
+ * @author Jonathan
+ *
+ */
+public class Page extends HTMLCacheGen {
+ public static final String AAFURL_TOOLS = "aaf_url.tools";
+ public static final String AAF_URL_TOOL_DOT = "aaf_url.tool.";
+ public static final String AAF_URL_CUIGUI = "aaf_url.cuigui"; // link to help
+ public static final String AAF_URL_GUI_ONBOARD = "aaf_url.gui_onboard";
+ public static final String AAF_URL_AAF_HELP = "aaf_url.aaf_help";
+ public static final String AAF_URL_CADI_HELP = "aaf_url.cadi_help";
+ public static final String PERM_CA_TYPE = Define.ROOT_NS() + ".ca";
+
+ public static enum BROWSER {iPhone,html5,ie,ieOld};
+
+ public static final int MAX_LINE=20;
+
+ protected static final String[] NO_FIELDS = new String[0];
+
+ private static final String BROWSER_TYPE = "BROWSER_TYPE";
+
+ private final String bcName, bcUrl;
+ private final String[] fields;
+
+ public final boolean no_cache;
+
+ // Note: Only access is synchronized in "getPerm"
+ private final static Map<String,Map<String,Permission>> perms = new HashMap<String,Map<String,Permission>>();
+
+ public String name() {
+ return bcName;
+ }
+
+ public String url() {
+ return bcUrl;
+ }
+
+ public String[] fields() {
+ return fields;
+ }
+
+ public Page(AuthzEnv env, String name, String url, Enum<?>[] en, final NamedCode ...content) throws APIException, IOException {
+ super(CacheGen.PRETTY, new PageCode(env, 1, content));
+ fields = new String[en.length];
+ int i=-1;
+ for(Enum<?> p : en) {
+ fields[++i]=p.name();
+ }
+
+ bcName = name;
+ bcUrl = url;
+ // Mark which fields must be "no_cache"
+ boolean no_cacheTemp=false;
+ for(NamedCode nc : content) {
+ if(nc.no_cache()) {
+ no_cacheTemp=true;
+ break;
+ }
+ }
+ no_cache=no_cacheTemp;
+ }
+ public Page(AuthzEnv env, String name, String url, String [] fields, final NamedCode ... content) throws APIException,IOException {
+ this(env,name,url,1,fields,content);
+ }
+
+ public Page(AuthzEnv env, String name, String url, int backdots, String [] fields, final NamedCode ... content) throws APIException,IOException {
+ super(CacheGen.PRETTY, new PageCode(env, backdots, content));
+ if(fields==null) {
+ this.fields = new String[0];
+ } else {
+ this.fields = fields;
+ }
+ bcName = name;
+ bcUrl = url;
+ // Mark which fields must be "no_cache"
+ boolean no_cacheTemp=false;
+ for(NamedCode nc : content) {
+ if(nc.no_cache()) {
+ no_cacheTemp=true;
+ break;
+ }
+ }
+ no_cache=no_cacheTemp;
+ }
+
+
+ private static class PageCode implements Code<HTMLGen> {
+ private static final String AAF_GUI_TITLE = "aaf_gui_title";
+
+ private final ContentCode[] content;
+ private final Slot browserSlot;
+ private final int backdots;
+ protected AuthzEnv env;
+ private StaticSlot sTheme;
+
+ public PageCode(AuthzEnv env, int backdots, final ContentCode[] content) {
+ this.content = content;
+ this.backdots = backdots;
+ browserSlot = env.slot(BROWSER_TYPE);
+ sTheme = env.staticSlot(CachingFileAccess.CFA_WEB_PATH);
+ this.env = env;
+ }
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ // Note: I found that App Storage saves everything about the page, or not. Thus, if you declare the page uncacheable, none of the
+ // Artifacts, like JPGs are stored, which makes this feature useless for Server driven elements
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ switch(browser(trans,browserSlot)) {
+ case ieOld:
+ case ie:
+ hgen.directive("!DOCTYPE html");
+ hgen.directive("meta", "http-equiv=X-UA-Compatible","content=IE=11");
+ default:
+ }
+ }
+ });
+ hgen.html();
+ final String title = env.getProperty(AAF_GUI_TITLE,"Authentication/Authorization Framework");
+ final String theme = env.get(sTheme);
+ Mark head = hgen.head();
+ hgen.leaf(TITLE).text(title).end();
+ hgen.imports(new Imports(backdots).css(theme + "/aaf5.css")
+ .js(theme + "/comm.js")
+ .js(theme + "/console.js")
+ .js(theme + "/common.js"));
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ switch(browser(trans,browserSlot)) {
+ case iPhone:
+ hgen.imports(new Imports(backdots).css(theme + "/aaf5iPhone.css"));
+ break;
+ case ie:
+ case ieOld:
+ hgen.js().text("document.createElement('header');")
+ .text("document.createElement('nav');")
+ .done();
+ case html5:
+ hgen.imports(new Imports(backdots).css(theme + "/aaf5Desktop.css"));
+ break;
+ }
+ }
+ });
+ hgen.end(head);
+
+ Mark body = hgen.body();
+ Mark header = hgen.header();
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI state, AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen xgen)
+ throws APIException, IOException {
+ // Obtain Server Info, and print
+ // AT&T Only
+ String env = trans.getProperty(Config.AAF_ENV,"N/A");
+ xgen.leaf(H1).text(title + " on " + env).end();
+ xgen.leaf("p","id=version").text("AAF Version: " + state.deployedVersion).end();
+
+ // Obtain User Info, and print
+ TaggedPrincipal p = trans.getUserPrincipal();
+ String user,secured;
+ if(p==null) {
+ user = "please choose a Login Authority";
+ secured = "NOT Secure!";
+ } else {
+ user = p.personalName();
+ secured = p.tag();
+ }
+ xgen.leaf("p","id=welcome").text("Welcome, ")
+ .text(user)
+ .text("<sup>")
+ .text(secured)
+ .text("</sup>").end();
+
+ switch(browser(trans,browserSlot)) {
+ case ieOld:
+ case ie:
+ xgen.incr("h5").text("This app is Mobile First HTML5. Internet Explorer "
+ + " does not support all HTML5 standards. Old, non TSS-Standard versions may not function correctly.").br()
+ .text(" For best results, use a highly compliant HTML5 browser like Firefox.")
+ .end();
+ break;
+ default:
+ }
+ }
+ });
+
+ hgen.hr();
+
+ int cIdx;
+ ContentCode nc;
+ // If BreadCrumbs, put here
+ if(content.length>0 && content[0] instanceof BreadCrumbs) {
+ nc = content[0];
+ Mark ctnt = hgen.divID(nc.idattrs());
+ nc.code(cache, hgen);
+ hgen.end(ctnt);
+ cIdx = 1;
+ } else {
+ cIdx = 0;
+ }
+
+ hgen.end(header);
+
+ Mark inner = hgen.divID("inner");
+ // Content
+ for(int i=cIdx;i<content.length;++i) {
+ nc = content[i];
+ Mark ctnt = hgen.divID(nc.idattrs());
+ nc.code(cache, hgen);
+ hgen.end(ctnt);
+ }
+
+ hgen.end(inner);
+
+ // Navigation - Using older Nav to work with decrepit IE versions
+
+ Mark nav = hgen.divID("nav");
+ hgen.incr("h2").text("Related Links").end();
+ hgen.incr(UL);
+ String aaf_help = env.getProperty(AAF_URL_AAF_HELP,null);
+ if(aaf_help!=null) {
+ hgen.leaf(LI).leaf(A,"href="+env.getProperty(AAF_URL_AAF_HELP),"target=_blank").text("AAF WIKI").end(2);
+ String sub = env.getProperty(AAF_URL_AAF_HELP+".sub");
+ if(sub!=null) {
+ hgen.incr(UL,"style=margin-left:5%");
+ for(String s : Split.splitTrim(',', sub)) {
+ hgen.leaf(LI).leaf(A,"href="+env.getProperty(AAF_URL_AAF_HELP+".sub."+s),"target=_blank").text(s.replace('+', ' ')).end(2);
+ }
+ hgen.end();
+ }
+ }
+ aaf_help = env.getProperty(AAF_URL_CADI_HELP,null);
+ if(aaf_help!=null) {
+ hgen.leaf(LI).leaf(A,"href="+aaf_help,"target=_blank").text("CADI WIKI").end(2);
+ }
+ String tools = env.getProperty(AAFURL_TOOLS);
+ if(tools!=null) {
+ hgen.hr()
+ .incr(HTMLGen.UL,"style=margin-left:5%")
+ .leaf(HTMLGen.H3).text("Related Tools").end();
+
+ for(String tool : Split.splitTrim(',',tools)) {
+ hgen.leaf(LI).leaf(A,"href="+env.getProperty(AAF_URL_TOOL_DOT+tool),"target=_blank").text(tool.replace('+', ' ')).end(2);
+ }
+ hgen.end();
+ }
+ hgen.end();
+
+ hgen.hr();
+
+ hgen.end(nav);
+ // Footer - Using older Footer to work with decrepit IE versions
+ Mark footer = hgen.divID("footer");
+ hgen.textCR(1, env.getProperty(AAF_GUI.AAF_GUI_COPYRIGHT))
+ .end(footer);
+
+ hgen.end(body);
+ hgen.endAll();
+ }
+ }
+
+ public static String getBrowserType() {
+ return BROWSER_TYPE;
+ }
+
+ /**
+ * It's IE if int >=0
+ *
+ * Use int found in "ieVersion"
+ *
+ * Official IE 7
+ * Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322;
+ * .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
+ * Official IE 8
+ * Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2;
+ * .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; ATT)
+ *
+ * IE 11 Compatibility
+ * Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; SLCC2; .NET CLR 2.0.50727;
+ * .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 1.1.4322; .NET4.0C; .NET4.0E; InfoPath.3; HVD; ATT)
+ *
+ * IE 11 (not Compatiblity)
+ * Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727;
+ * .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 1.1.4322; .NET4.0C; .NET4.0E; InfoPath.3; HVD; ATT)
+ *
+ * @param trans
+ * @return
+ */
+ public static BROWSER browser(AuthzTrans trans, Slot slot) {
+ BROWSER br = trans.get(slot, null);
+ if(br==null) {
+ String agent = trans.agent();
+ int msie;
+ if(agent.contains("iPhone") /* other phones? */) {
+ br=BROWSER.iPhone;
+ } else if ((msie = agent.indexOf("MSIE"))>=0) {
+ msie+=5;
+ int end = agent.indexOf(";",msie);
+ float ver;
+ try {
+ ver = Float.valueOf(agent.substring(msie,end));
+ br = ver<8f?BROWSER.ieOld:BROWSER.ie;
+ } catch (Exception e) {
+ br = BROWSER.ie;
+ }
+ } else {
+ br = BROWSER.html5;
+ }
+ trans.put(slot,br);
+ }
+ return br;
+ }
+
+ /*
+ * Get, rather than create each time, permissions for validations
+ */
+ protected static synchronized Permission getPerm(String instance, String action) {
+ Map<String,Permission> msp = perms.get(instance);
+ Permission p;
+ if(msp==null) {
+ msp = new HashMap<String,Permission>();
+ perms.put(instance, msp);
+ p=null;
+ } else {
+ p = msp.get(instance);
+ }
+ if(p==null) {
+ p=new AAFPermission(PERM_CA_TYPE,instance,action);
+ msp.put(action, p);
+ }
+ return p;
+ }
+
+ protected static String getSingleParam(HttpServletRequest req, String tag) {
+ String values[] = req.getParameterValues(tag);
+ return values.length<1?null:values[0];
+ }
+
+
+}
+
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/SlotCode.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/SlotCode.java
new file mode 100644
index 00000000..b457fc9b
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/SlotCode.java
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import org.onap.aaf.misc.env.EnvStore;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TransStore;
+
+public abstract class SlotCode<TRANS extends TransStore> extends NamedCode {
+ private Slot[] slots;
+
+ public SlotCode(boolean no_cache,EnvStore<?> env, String root, Enum<?> ... params) {
+ super(no_cache,root);
+ slots = new Slot[params.length];
+ for(int i=0;i<params.length;++i) {
+ slots[i] = env.slot(root + '.' + params[i].name());
+ }
+ }
+
+ public<T> T get(TRANS trans,Enum<?> en, T dflt) {
+ return get(trans,en.ordinal(),dflt);
+ }
+
+ public<T> T get(TRANS trans,int idx, T dflt) {
+ if(idx>slots.length) {
+ return dflt;
+ }
+ return trans.get(slots[idx],dflt);
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Table.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Table.java
new file mode 100644
index 00000000..6839a9ab
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Table.java
@@ -0,0 +1,229 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TABLE;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TD;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TR;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.Trans;
+import org.onap.aaf.misc.env.TransStore;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.Code;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+import org.onap.aaf.misc.xgen.html.State;
+
+public class Table<S extends State<Env>, TRANS extends TransStore> extends NamedCode {
+ private final Slot ROW_MSG_SLOT, EMPTY_TABLE_SLOT;
+ private final String title;
+ private final String[] columns;
+ private final Rows rows;
+ private Code<HTMLGen> other;
+// private DynamicCode<HTMLGen, AuthGUI, AuthzTrans> prefix,postfix;
+
+ public Table(String title, TRANS trans, Data<S,TRANS> data, Code<HTMLGen> other, String name, String ... attrs) {
+ this(title,trans,data,name, attrs);
+ this.other = other;
+ }
+
+ public Table(String title, TRANS trans, Data<S,TRANS> data, String name, String ... attrs) {
+ super(true,name);
+// prefix=postfix=null;
+ for(String a : attrs) {
+ addAttr(false, a);
+ }
+ ROW_MSG_SLOT=trans.slot("TABLE_ROW_MSG");
+ EMPTY_TABLE_SLOT=trans.slot("TABLE_EMPTY");
+ this.columns = data.headers();
+ boolean alt = false;
+ for(String s : attrs) {
+ if("class=std".equals(s) || "class=stdform".equals(s)) {
+ alt=true;
+ }
+ }
+ rows = new Rows(data,alt?1:0);
+ this.title = title;
+ // Derive an ID from title (from no spaces, etc), and prepend to IDAttributes (Protected from NamedCode)
+ addAttr(true,title(trans).replaceAll("\\s",""));
+
+ other = null;
+ }
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,S,TRANS>() {
+ @Override
+ public void code(S state, TRANS trans, Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException {
+ rows.data.prefix(state, trans, cache, xgen);
+ }
+ });
+ Mark table = new Mark();
+ Mark tr = new Mark();
+
+ hgen.incr(table,TABLE);
+ if(title==null) {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,S,TRANS>() {
+ @Override
+ public void code(S state, TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ hgen.leaf("caption", "class=title").text(title(trans)).end();
+ }
+ });
+ } else {
+ hgen.leaf("caption", "class=title").text(title).end();
+ }
+ hgen.incr(tr,TR);
+ for(String column : columns) {
+ hgen.leaf("th").text(column).end();
+ }
+ hgen.end(tr);
+
+ // Load Rows Dynamically
+ cache.dynamic(hgen, rows);
+ // End Table
+ hgen.end(table);
+
+ if(other!=null) {
+ other.code(cache,hgen);
+ }
+
+ // Print Message from Row Gathering, if available
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,S,TRANS>() {
+ @Override
+ public void code(S state, TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String msg;
+ if((msg = trans.get(EMPTY_TABLE_SLOT, null))!=null) {
+ hgen.incr("style").text("#inner tr,caption,input,p.preamble {display: none;}#inner p.notfound {margin: 0px 0px 0px 20px}").end();
+ hgen.incr(HTMLGen.P,"class=notfound").text(msg).end().br();
+ } else if((msg=trans.get(ROW_MSG_SLOT,null))!=null) {
+ hgen.p(msg).br();
+ }
+ }
+ });
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,S,TRANS>() {
+ @Override
+ public void code(S state, TRANS trans, Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException {
+ rows.data.postfix(state, trans, cache, xgen);
+ }
+ });
+
+ }
+
+ protected String title(TRANS trans) {
+ return title;
+ }
+
+ public static class Cells {
+ public static final Cells EMPTY = new Cells();
+ private Cells() {
+ cells = new AbsCell[0][0];
+ msg = "No Data Found";
+ }
+
+ public Cells(ArrayList<AbsCell[]> arrayCells, String msg) {
+ cells = new AbsCell[arrayCells.size()][];
+ arrayCells.toArray(cells);
+ this.msg = msg;
+ }
+ public AbsCell[][] cells;
+ public String msg;
+
+ }
+
+ public interface Data<S extends State<Env>, TRANS extends Trans> {
+ // Note: Trans is not first to avoid Method Name Collision
+ public void prefix(S state, TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen);
+ public Cells get(TRANS trans,S state);
+ public void postfix(S state, TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen);
+ public String[] headers();
+ }
+
+ private class Rows extends DynamicCode<HTMLGen,S,TRANS> {
+ private Data<S,TRANS> data;
+ private int alt;
+
+ public Rows(Data<S,TRANS> data, int alt) {
+ this.data = data;
+ this.alt = alt;
+ }
+
+ @Override
+ public void code(final S state, final TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ Mark tr = new Mark();
+ Mark td = new Mark();
+
+ int alt = this.alt;
+ Cells cells = data.get(trans,state);
+ if(cells.cells.length>0) {
+ for(AbsCell[] row : cells.cells) {
+ if(row.length==0) {
+ hgen.text("</table>")
+ .hr()
+ .text("<table>");
+ } else {
+ switch(alt) {
+ case 1:
+ alt=2;
+ case 0:
+ hgen.incr(tr,TR);
+ break;
+ default:
+ alt=1;
+ hgen.incr(tr,TR,"class=alt");
+ }
+ for(AbsCell cell :row) {
+ hgen.leaf(td, TD,cell.attrs());
+ cell.write(hgen);
+ hgen.end(td);
+ }
+ hgen.end(tr);
+ }
+ }
+ // Pass Msg back to Table code, in order to place after Table Complete
+ if(cells.msg!=null) {
+ trans.put(ROW_MSG_SLOT,cells.msg);
+ }
+ } else {
+ trans.put(EMPTY_TABLE_SLOT,cells.msg);
+ }
+ }
+ }
+
+// public Table<S,TRANS> setPrefix(DynamicCode<HTMLGen, AuthGUI, AuthzTrans> dynamicCode) {
+// prefix = dynamicCode;
+// return this;
+// }
+//
+// public Table<S,TRANS> setPostfix(DynamicCode<HTMLGen, AuthGUI, AuthzTrans> dynamicCode) {
+// postfix = dynamicCode;
+// return this;
+// }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/XFrameFilter.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/XFrameFilter.java
new file mode 100644
index 00000000..ae71d5bf
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/XFrameFilter.java
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.gui;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+public class XFrameFilter implements Filter {
+ enum TYPE {none,self};
+ // Note: Content-Security Params need to be worked out for GUI before activating.
+ private final String xframe;//,csp;
+
+ public XFrameFilter(TYPE type) {
+ switch(type) {
+ case self:
+ xframe="SAMEORIGIN";
+// csp="default-src 'self'";
+ break;
+ case none:
+ default:
+ xframe="DENY";
+// csp="default-src 'none'";
+ break;
+
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) throws IOException, ServletException {
+ if(resp instanceof HttpServletResponse) {
+ @SuppressWarnings("unused")
+ HttpServletResponse hresp = (HttpServletResponse)resp;
+ ((HttpServletResponse)resp).addHeader("X-Frame-Options", xframe);
+// ((HttpServletResponse)resp).addHeader("Content-Security-Policy",csp);
+ }
+ fc.doFilter(req, resp);
+ }
+
+ @Override
+ public void init(FilterConfig fc) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java
new file mode 100644
index 00000000..05ee21b0
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java
@@ -0,0 +1,334 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.auth.rserv.HttpMethods;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.Symm;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Api;
+import aaf.v2_0.Api.Route;
+
+public class ApiDocs extends Page {
+ // Package on purpose
+ private static final String HREF = "/gui/api";
+ private static final String NAME = "AAF RESTful API";
+ private static final String fields[] = {};
+ private static final String ERROR_LINK = "<a href=\"./example/"
+ + "YXBwbGljYXRpb24vRXJyb3IranNvbg=="
+// + Symm.base64noSplit().encode("application/Error+json")
+ + "\">JSON</a> "
+ + "<a href=\"./example/"
+ + "YXBwbGljYXRpb24vRXJyb3IreG1s"
+// + Symm.base64noSplit().encode("application/Error+xml")
+ + "\">XML</a> ";
+
+
+ public ApiDocs(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new Preamble(gui),
+ new Table<AAF_GUI,AuthzTrans>("AAF API Reference",gui.env.newTransNoAvg(),new Model(), "class=std")
+ );
+ }
+
+ private static class Preamble extends NamedCode {
+
+ private static final String I = "i";
+ private final String fs_url;
+
+ public Preamble(AAF_GUI gui) {
+ super(false, "preamble");
+ fs_url = gui.access.getProperty("fs_url", "");
+ }
+
+ @Override
+ public void code(Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException {
+ xgen.leaf(HTMLGen.H1).text("AAF 2.0 RESTful interface").end()
+ .hr();
+ xgen.leaf(HTMLGen.H2).text("Accessing RESTful").end();
+ xgen.incr(HTMLGen.UL)
+ .leaf(HTMLGen.LI).text("AAF RESTful service is secured by the following:").end()
+ .incr(HTMLGen.UL)
+ .leaf(HTMLGen.LI).text("The Client must utilize HTTP/S. Non Secure HTTP is not acceptable").end()
+ .leaf(HTMLGen.LI).text("The Client MUST supply an Identity validated by one of the following mechanisms").end()
+ .incr(HTMLGen.UL)
+ .leaf(HTMLGen.LI).text("Valid Global Login Cookie (CSP)").end()
+ .leaf(HTMLGen.LI).text("BASIC AUTH protocol using CSO Registered MechID, provisioned in AAF").end()
+ .leaf(HTMLGen.LI).text("BASIC AUTH protocol using ATTUID@csp.att.com, Global Login Password").end()
+ .leaf(HTMLGen.LI).text("(Available 3rd Qtr 2015) Valid tGuard Login Cookie").end()
+ .leaf(HTMLGen.LI).text("(Near Future) Application level Certificate").end()
+ .end()
+ .end()
+ .leaf(HTMLGen.LI).text("Responses").end()
+ .incr(HTMLGen.UL)
+ .leaf(HTMLGen.LI).text("Each API Entity listed shows what structure will be accepted by service (ContentType) "
+ + "or responded with by service (Accept). Therefore, use these in making your call. Critical for PUT/POST.").end()
+ .leaf(HTMLGen.LI).text("Each API call may respond with JSON or XML. Choose the ContentType/Accept that has "
+ + "+json after the type for JSON or +xml after the Type for XML").end()
+ .leaf(HTMLGen.LI).text("XSDs for Versions").end()
+ .incr(HTMLGen.UL)
+ .leaf(HTMLGen.LI).leaf(HTMLGen.A,"href=" + fs_url + "/aaf_2_0.xsd").text("API 2.0").end().end()
+ .end()
+ .leaf(HTMLGen.LI).text("AAF can support multiple Versions of the API. Choose the ContentType/Accept that has "
+ + "the appropriate version=?.?").end()
+ .leaf(HTMLGen.LI).text("All Errors coming from AAF return AT&T Standard Error Message as a String: " + ERROR_LINK
+ + " (does not apply to errors from Container)").end()
+ .end()
+ .leaf(HTMLGen.LI).text("Character Restrictions").end()
+ .incr(HTMLGen.UL)
+ .leaf(HTMLGen.LI).text("Character Restrictions must depend on the Enforcement Point used").end()
+ .leaf(HTMLGen.LI).text("Most AAF usage will be AAF Enforcement Point Characters for Instance and Action are:")
+ .br().br().leaf(I).text("a-zA-Z0-9,.()_-=%").end()
+ .br().br().text("For Instance, you may declare a multi-dimensional key with : (colon) separator, example:").end()
+ .br().leaf(I).text(":myCluster:myKeyspace").end()
+ .br().br().text("The * (asterix) may be used as a wild-card by itself or within the multi-dimensional key, example:")
+ .br().leaf(I).text(":myCluster:*").end()
+ .br().br().text("The % (percent) character can be used as an Escape Character. Applications can use % followed by 2 hexadecimal "
+ + "digits to cover odd keys. It is their code, however, which must translate.")
+ .br().br().text("The = (equals) is allowed so that Applications can pass Base64 encodations of binary keys").end()
+ .leaf(HTMLGen.LI).text("Ask for a Consultation on how these are typically used, or, if your tool is the only Enforcement Point, if set may be expanded").end()
+ .end()
+ .end();
+ /*
+
+ The Content is defined in the AAF XSD - TODO Add aaf.xsd”;
+ Character Restrictions
+
+ URLs impose restrictions on characters which have specific meanings. This means you cannot have these characters in the Field Content you send
+ “#” is a “Fragment URL”, or anchor. Content after this Character is not sent. AAF cannot do anything about this… don’t use it.
+ “?=&”. These are used to delineate Parameters.
+ “/“ is used to separate fields
+ */
+ }
+
+ };
+ /**
+ * Implement the Table Content for Permissions by User
+ *
+ * @author Jonathan
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ public static final String[] HEADERS = new String[] {"Entity","Method","Path Info","Description"};
+ private static final TextCell BLANK = new TextCell("");
+
+ @Override
+ public String[] headers() {
+ return HEADERS;
+ }
+
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final ArrayList<AbsCell[]> ns = new ArrayList<AbsCell[]>();
+ final ArrayList<AbsCell[]> perms = new ArrayList<AbsCell[]>();
+ final ArrayList<AbsCell[]> roles = new ArrayList<AbsCell[]>();
+ final ArrayList<AbsCell[]> user = new ArrayList<AbsCell[]>();
+ final ArrayList<AbsCell[]> aafOnly = new ArrayList<AbsCell[]>();
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+
+
+ final TimeTaken tt = trans.start("AAF APIs",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Api> fa = client.read("/api",gui.getDF(Api.class));
+ if(fa.get(5000)) {
+ tt.done();
+ TimeTaken tt2 = trans.start("Load Data", Env.SUB);
+ try {
+ if(fa.value!=null)for(Route r : fa.value.getRoute()) {
+ String path = r.getPath();
+ // Build info
+ StringBuilder desc = new StringBuilder();
+
+ desc.append("<p class=double>");
+ desc.append(r.getDesc());
+
+ if(r.getComments().size()>0) {
+ for(String ct : r.getComments()) {
+ desc.append("</p><p class=api_comment>");
+ desc.append(ct);
+ }
+ }
+
+ if(r.getParam().size()>0) {
+ desc.append("<hr><p class=api_label>Parameters</p>");
+
+ for(String params : r.getParam()) {
+ String param[] = params.split("\\s*\\|\\s*");
+ desc.append("</p><p class=api_contentType>");
+ desc.append(param[0]);
+ desc.append(" : ");
+ desc.append(param[1]);
+ if("true".equalsIgnoreCase(param[2])) {
+ desc.append(" (Required)");
+ }
+ }
+ }
+
+
+ if(r.getExpected()!=0) {
+ desc.append("</p><p class=api_label>Expected HTTP Code</p><p class=api_comment>");
+ desc.append(r.getExpected());
+ }
+
+ if(r.getExplicitErr().size()!=0) {
+ desc.append("</p><p class=api_label>Explicit HTTP Error Codes</p><p class=api_comment>");
+ boolean first = true;
+ for(int ee : r.getExplicitErr()) {
+ if(first) {
+ first = false;
+ } else {
+ desc.append(", ");
+ }
+ desc.append(ee);
+ }
+ }
+
+ desc.append("</p><p class=api_label>");
+ desc.append("GET".equals(r.getMeth())?"Accept:":"ContentType:");
+ Collections.sort(r.getContentType());
+ if(r.getPath().startsWith("/authn/basicAuth")) {
+ desc.append("</p><p class=api_contentType>text/plain");
+ }
+ for(String ct : r.getContentType()) {
+ if(ct.contains("version=2")) {
+ desc.append("</p><p class=api_contentType><a href=\"./example/");
+ try {
+ desc.append(Symm.base64noSplit.encode(ct));
+ } catch (IOException e) {
+ throw new CadiException(e);
+ }
+ desc.append("\"/>");
+ desc.append(ct);
+ desc.append("</a>");
+ }
+ }
+ desc.append("</p>");
+
+
+ AbsCell[] sa = new AbsCell[] {
+ null,
+ new TextCell(r.getMeth(),"class=right"),
+ new TextCell(r.getPath()),
+ new TextCell(desc.toString()),
+ };
+
+ if(path.startsWith("/authz/perm")) {
+ sa[0] = perms.size()==0?new TextCell("PERMISSION"):BLANK;
+ perms.add(sa);
+ } else if(path.startsWith("/authz/role") || path.startsWith("/authz/userRole")) {
+ sa[0] = roles.size()==0?new TextCell("ROLE"):BLANK;
+ roles.add(sa);
+ } else if(path.startsWith("/authz/ns")) {
+ sa[0] = ns.size()==0?new TextCell("NAMESPACE"):BLANK;
+ ns.add(sa);
+ } else if(path.startsWith("/authn/basicAuth")
+ || path.startsWith("/authn/validate")
+ || path.startsWith("/authz/user")) {
+ sa[0] = user.size()==0?new TextCell("USER"):BLANK;
+ user.add(sa);
+ } else {
+ sa[0] = aafOnly.size()==0?new TextCell("AAF ONLY"):BLANK;
+ aafOnly.add(sa);
+ }
+ }
+ //TODO if(trans.fish(p))
+ prepare(rv, perms,roles,ns,user);
+ } finally {
+ tt2.done();
+ }
+ } else {
+ gui.writeError(trans, fa, null, 0);
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e.getMessage());
+ } finally {
+ tt.done();
+ }
+
+ return new Cells(rv,null);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void prepare(ArrayList<AbsCell[]> rv, ArrayList<AbsCell[]> ... all) {
+ AbsCell lead;
+ AbsCell[] row;
+ for(ArrayList<AbsCell[]> al : all) {
+ if(al.size()>1) {
+ row = al.get(0);
+ lead = row[0];
+ row[0]=BLANK;
+ al.get(0).clone()[0]=BLANK;
+ Collections.sort(al, new Comparator<AbsCell[]>() {
+ @Override
+ public int compare(AbsCell[] ca1, AbsCell[] ca2) {
+ int meth = ((TextCell)ca1[2]).name.compareTo(
+ ((TextCell)ca2[2]).name);
+ if(meth == 0) {
+ return (HttpMethods.valueOf(((TextCell)ca1[1]).name).compareTo(
+ HttpMethods.valueOf(((TextCell)ca2[1]).name)));
+ } else {
+ return meth;
+ }
+ }
+ });
+ // set new first row
+ al.get(0)[0]=lead;
+
+ rv.addAll(al);
+ }
+ }
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiExample.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiExample.java
new file mode 100644
index 00000000..a98a16ca
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiExample.java
@@ -0,0 +1,133 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.Symm;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+/**
+ * Detail Page for Permissions
+ *
+ * @author Jonathan
+ *
+ */
+public class ApiExample extends Page {
+ public static final String HREF = "/gui/example/:tc";
+ public static final String NAME = "APIExample";
+
+ public ApiExample(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, 2/*backdots*/, new String[] {"API Code Example"},
+ new BreadCrumbs(breadcrumbs),
+ new Model(NAME)
+ );
+ }
+
+ private static class Model extends NamedCode {
+ private static final String WITH_OPTIONAL_PARAMETERS = "\n\n////////////\n Data with Optional Parameters \n////////////\n\n";
+
+ public Model(String name) {
+ super(false,name);
+ }
+
+ @Override
+ public void code(Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException {
+ Mark inner = xgen.divID("inner");
+ xgen.divID("example","class=std");
+ cache.dynamic(xgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException {
+ TimeTaken tt = trans.start("Code Example",Env.REMOTE);
+ try {
+ final String typecode;
+ int prefix = trans.path().lastIndexOf('/')+1;
+ String encoded = trans.path().substring(prefix);
+ typecode = Symm.base64noSplit.decode(encoded);
+ Future<String> fp = gui.client().read("/api/example/" + encoded,
+ "application/Void+json"
+ );
+ Future<String> fs2;
+ if(typecode.contains("Request+")) {
+ fs2 = gui.client().read("/api/example/" + encoded+"?optional=true",
+ "application/Void+json"
+ );
+ } else {
+ fs2=null;
+ }
+
+
+ if(fp.get(5000)) {
+ xgen.incr(HTMLGen.H1).text("Sample Code").end()
+ .incr(HTMLGen.H5).text(typecode).end();
+ xgen.incr("pre");
+ if(typecode.contains("+xml")) {
+ xgen.xml(fp.body());
+ if(fs2!=null && fs2.get(5000)) {
+ xgen.text(WITH_OPTIONAL_PARAMETERS);
+ xgen.xml(fs2.body());
+ }
+ } else {
+ xgen.text(fp.body());
+ if(fs2!=null && fs2.get(5000)) {
+ xgen.text(WITH_OPTIONAL_PARAMETERS);
+ xgen.text(fs2.body());
+ }
+ }
+ xgen.end();
+ } else {
+ xgen.incr(HTMLGen.H3)
+ .textCR(2,"Error from AAF Service")
+ .end();
+ gui.writeError(trans, fp, xgen, 0);
+ }
+
+ } catch (APIException e) {
+ throw e;
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new APIException(e);
+ }finally {
+ tt.done();
+ }
+ }
+
+ });
+ xgen.end(inner);
+ }
+ }
+
+}
+ \ No newline at end of file
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalAction.java
new file mode 100644
index 00000000..2797cd66
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalAction.java
@@ -0,0 +1,121 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Approval;
+import aaf.v2_0.Approvals;
+
+public class ApprovalAction extends Page {
+ public ApprovalAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,"Approvals",ApprovalForm.HREF, ApprovalForm.FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sAppr = gui.env.slot(ApprovalForm.NAME+'.'+ApprovalForm.FIELDS[0]);
+ final Slot sUser = gui.env.slot(ApprovalForm.NAME+'.'+ApprovalForm.FIELDS[1]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String[] appr = trans.get(sAppr,null);
+ String user = trans.get(sUser,null);
+ String lastPage = ApprovalForm.HREF;
+ if (user != null) {
+ lastPage += "?user="+user;
+ }
+
+ if(appr==null) {
+ hgen.p("No Approvals have been selected.");
+ } else {
+ Approval app;
+ final Approvals apps = new Approvals();
+ int count = 0;
+ for(String a : appr) {
+ if(a!=null) {
+ int idx = a.indexOf('|');
+ if(idx>=0) {
+ app = new Approval();
+ app.setStatus(a.substring(0,idx));
+ app.setTicket(a.substring(++idx));
+ app.setApprover(trans.getUserPrincipal().getName());
+ apps.getApprovals().add(app);
+ ++count;
+ }
+ }
+ }
+ if(apps.getApprovals().isEmpty()) {
+ hgen.p("No Approvals have been sent.");
+ } else {
+ TimeTaken tt = trans.start("AAF Update Approvals",Env.REMOTE);
+ try {
+ final int total = count;
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client) throws APIException, CadiException {
+ boolean fail2 = true;
+ Future<Approvals> fa = client.update("/authz/approval",gui.getDF(Approvals.class),apps);
+ if(fa.get(AAF_GUI.TIMEOUT)) {
+ // Do Remote Call
+ fail2 = false;
+ hgen.p(total + (total==1?" Approval has":" Approvals have") + " been Saved");
+ } else {
+ gui.writeError(trans, fa, hgen, 0);
+ }
+ return fail2;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+ }
+
+ hgen.br();
+ hgen.incr("a",true,"class=greenbutton","href="+lastPage).text("Back").end();
+ }
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalForm.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalForm.java
new file mode 100644
index 00000000..da552aeb
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApprovalForm.java
@@ -0,0 +1,299 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Form;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.ButtonCell;
+import org.onap.aaf.auth.gui.table.RadioCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextAndRefCell;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.auth.org.Organization;
+import org.onap.aaf.auth.org.OrganizationFactory;
+import org.onap.aaf.auth.org.Organization.Identity;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Approval;
+import aaf.v2_0.Approvals;
+
+public class ApprovalForm extends Page {
+ // Package on purpose
+ static final String NAME="Approvals";
+ static final String HREF = "/gui/approve";
+ static final String[] FIELDS = new String[] {"line[]","user"};
+
+
+ public ApprovalForm(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, FIELDS,
+
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(false, "filterByUser") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String user = trans.get(trans.env().slot(NAME+".user"),"");
+ hgen.incr("p", "class=userFilter")
+ .text("Filter by User:")
+ .tagOnly("input", "type=text", "value="+user, "id=userTextBox")
+ .tagOnly("input", "type=button", "onclick=userFilter('"+HREF+"');", "value=Go!")
+ .end();
+ }
+ });
+ }
+ },
+ new Form(true,new Table<AAF_GUI,AuthzTrans>("Approval Requests", gui.env.newTransNoAvg(),new Model(gui.env),"class=stdform"))
+ .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."),
+ new NamedCode(false, "selectAlljs") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ Mark jsStart = new Mark();
+ hgen.js(jsStart);
+ hgen.text("function selectAll(radioClass) {");
+ hgen.text("var radios = document.querySelectorAll(\".\"+radioClass);");
+ hgen.text("for (i = 0; i < radios.length; i++) {");
+ hgen.text("radios[i].checked = true;");
+ hgen.text("}");
+ hgen.text("}");
+ hgen.end(jsStart);
+ }
+ });
+
+ }
+
+ /**
+ * Implement the Table Content for Approvals
+ *
+ * @author Jonathan
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ //TODO come up with a generic way to do ILM Info (people page)
+ private static final String TODO_ILM_INFO = "TODO: ILM Info";
+ private static final String DOMAIN_OF_USER = "@DOMAIN";
+
+ private static final String[] headers = new String[] {"Identity","Request","Approve","Deny"};
+ private Slot sUser;
+
+ public Model(AuthzEnv env) {
+ sUser = env.slot(NAME+".user");
+ }
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String userParam = trans.get(sUser, null);
+ ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ String msg = null;
+ TimeTaken tt = trans.start("AAF Get Approvals for Approver",Env.REMOTE);
+ try {
+ final List<Approval> pendingApprovals = new ArrayList<Approval>();
+ final List<Integer> beginIndicesPerApprover = new ArrayList<Integer>();
+ int numLeft = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Integer>() {
+ @Override
+ public Integer code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Approvals> fa = client.read("/authz/approval/approver/"+trans.user(),gui.getDF(Approvals.class));
+ int numLeft = 0;
+ if(fa.get(AAF_GUI.TIMEOUT)) {
+
+ if(fa.value!=null) {
+ for (Approval appr : fa.value.getApprovals()) {
+ if (appr.getStatus().equals("pending")) {
+ if (userParam!=null) {
+ if (!appr.getUser().equalsIgnoreCase(userParam)) {
+ numLeft++;
+ continue;
+ }
+ }
+ pendingApprovals.add(appr);
+ }
+ }
+ }
+
+ String prevApprover = null;
+ int overallIndex = 0;
+
+ for (Approval appr : pendingApprovals) {
+ String currApprover = appr.getApprover();
+ if (!currApprover.equals(prevApprover)) {
+ prevApprover = currApprover;
+ beginIndicesPerApprover.add(overallIndex);
+ }
+ overallIndex++;
+ }
+ }
+ return numLeft;
+ }
+ });
+
+ if (pendingApprovals.size() > 0) {
+ // Only add select all links if we have approvals
+ AbsCell[] selectAllRow = new AbsCell[] {
+ AbsCell.Null,
+ AbsCell.Null,
+ new ButtonCell("all", "onclick=selectAll('approve')", "class=selectAllButton"),
+ new ButtonCell("all", "onclick=selectAll('deny')", "class=selectAllButton")
+ };
+ rv.add(selectAllRow);
+ }
+
+ int line=-1;
+
+ while (beginIndicesPerApprover.size() > 0) {
+ int beginIndex = beginIndicesPerApprover.remove(0);
+ int endIndex = (beginIndicesPerApprover.isEmpty()?pendingApprovals.size():beginIndicesPerApprover.get(0));
+ List<Approval> currApproverList = pendingApprovals.subList(beginIndex, endIndex);
+
+ String currApproverFull = currApproverList.get(0).getApprover();
+ String currApproverShort = currApproverFull.substring(0,currApproverFull.indexOf('@'));
+ String currApprover = (trans.user().indexOf('@')<0?currApproverShort:currApproverFull);
+ if (!currApprover.equals(trans.user())) {
+ AbsCell[] approverHeader;
+ if (currApproverFull.substring(currApproverFull.indexOf('@')).equals(DOMAIN_OF_USER)) {
+ approverHeader = new AbsCell[] {
+ new TextAndRefCell("Approvals Delegated to Me by ", currApprover,
+ TODO_ILM_INFO + currApproverShort,
+ true,
+ new String[] {"colspan=4", "class=head"})
+ };
+ } else {
+ approverHeader = new AbsCell[] {
+ new TextCell("Approvals Delegated to Me by " + currApprover,
+ new String[] {"colspan=4", "class=head"})
+ };
+ }
+ rv.add(approverHeader);
+ }
+
+ // Sort by User Requesting
+ Collections.sort(currApproverList, new Comparator<Approval>() {
+ @Override
+ public int compare(Approval a1, Approval a2) {
+ return a1.getUser().compareTo(a2.getUser());
+ }
+ });
+
+ String prevUser = null;
+ boolean userOK=true;
+
+ for (Approval appr : currApproverList) {
+ if(++line<MAX_LINE) { // limit number displayed at one time.
+ AbsCell userCell;
+ String user = appr.getUser();
+ if(user.equals(prevUser)) {
+ userCell = AbsCell.Null;
+ } else if (user.endsWith(DOMAIN_OF_USER)){
+ userOK=true;
+ String title;
+ Organization org = OrganizationFactory.obtain(trans.env(), user);
+ if(org==null) {
+ title="";
+ } else {
+ Identity au = org.getIdentity(trans, user);
+ if(au!=null) {
+ if(au.type().equals("MECHID")) {
+ Identity managedBy = au.responsibleTo();
+ if(managedBy==null) {
+ title ="title=" + au.type();
+ } else {
+ title="title=Sponsor is " + managedBy.fullName();
+ }
+ } else {
+ title="title=" + au.fullName();
+ }
+ } else {
+ userOK=false;
+ title="title=Not a User at " + org.getName();
+ }
+ }
+ userCell = new RefCell(prevUser=user,
+ TODO_ILM_INFO+user.substring(0, user.length()-DOMAIN_OF_USER.length()),
+ true,
+ title);
+ } else {
+ userCell = new TextCell(prevUser=user);
+ }
+ AbsCell[] sa = new AbsCell[] {
+ userCell,
+ new TextCell(appr.getMemo()),
+ userOK?new RadioCell("line."+ line,"approve", "approved|"+appr.getTicket()):new TextCell(""),
+ new RadioCell("line."+ line,"deny", "denied|"+appr.getTicket())
+ };
+ rv.add(sa);
+ } else {
+ ++numLeft;
+ }
+ }
+ }
+ if(numLeft>0) {
+ msg = "After these, there will be " + numLeft + " approvals left to process";
+ }
+ if(rv.size()==0) {
+ if (numLeft>0) {
+ msg = "No Approvals to process at this time for user " + userParam +". You have "
+ + numLeft + " other approvals to process.";
+ } else {
+ msg = "No Approvals to process at this time";
+ }
+ }
+ } catch (Exception e) {
+ trans.error().log(e);
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,msg);
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java
new file mode 100644
index 00000000..1bf0ed76
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java
@@ -0,0 +1,219 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Holder;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.util.Vars;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.Data.TYPE;
+import org.onap.aaf.misc.env.util.IPValidator;
+import org.onap.aaf.misc.env.util.Split;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Error;
+import certman.v1_0.Artifacts;
+import certman.v1_0.Artifacts.Artifact;
+
+public class CMArtiChangeAction extends Page {
+ public CMArtiChangeAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,CMArtiChangeForm.NAME,CMArtiChangeForm.HREF, CMArtiChangeForm.fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sID = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[0]);
+ final Slot sMachine = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[1]);
+ final Slot sNS = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[2]);
+ final Slot sDirectory = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[3]);
+ final Slot sCA = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[4]);
+ final Slot sOSUser = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[5]);
+ final Slot sRenewal = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[6]);
+ final Slot sNotify = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[7]);
+ final Slot sCmd = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[8]);
+ final Slot sOther = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[9]);
+ final Slot sType = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[10]);
+ final Slot sSans = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[11]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+trans.info().log("Step 1");
+ final Artifact arti = new Artifact();
+ final String machine = trans.get(sMachine,null);
+ final String ca = trans.get(sCA, null);
+ final String sans = ((String)trans.get(sSans,null));
+ if(sans!=null) {
+ for(String s: Split.splitTrim(',', sans)) {
+ arti.getSans().add(s);
+ }
+ }
+ // Disallow IP entries, except by special Permission
+ if(!trans.fish(getPerm(ca,"ip"))) {
+ boolean ok=true;
+ if(IPValidator.ip(machine)) {
+ ok=false;
+ }
+ if(ok) {
+ for(String s: arti.getSans()) {
+ if(IPValidator.ip(s)) {
+ ok=false;
+ break;
+ }
+ }
+ }
+ if(!ok) {
+ hgen.p("Policy Failure: IPs in certificates are only allowed by Exception.");
+ return;
+ }
+ }
+
+ // Disallow Domain based Definitions without exception
+ if(machine.startsWith("*")) { // Domain set
+ if(!trans.fish(getPerm(ca, "domain"))) {
+ hgen.p("Policy Failure: Domain Artifact Declarations are only allowed by Exception.");
+ return;
+ }
+ }
+
+ arti.setMechid((String)trans.get(sID,null));
+ arti.setMachine(machine);
+ arti.setNs((String)trans.get(sNS,null));
+ arti.setDir((String)trans.get(sDirectory,null));
+ arti.setCa(ca);
+ arti.setOsUser((String)trans.get(sOSUser, null));
+ arti.setRenewDays(Integer.parseInt((String)trans.get(sRenewal, null)));
+ arti.setNotification((String)trans.get(sNotify, null));
+ String[] checkbox = trans.get(sType,null);
+ for(int i=0;i<CMArtiChangeForm.types.length;++i) {
+ if("on".equals(checkbox[i])) {
+ arti.getType().add(CMArtiChangeForm.types[i]);
+ }
+ }
+
+ // Run Validations
+ if (arti.getMechid()==null || arti.getMechid().indexOf('@')<=0) {
+ hgen.p("Data Entry Failure: Please enter a valid ID, including domain.");
+ // VALIDATE OTHERS?
+ } else { // everything else is checked by Server
+
+ try {
+ final Artifacts artifacts = new Artifacts();
+ artifacts.getArtifact().add(arti);
+ final Holder<Boolean> ok = new Holder<Boolean>(false);
+ final Holder<Boolean> deleted = new Holder<Boolean>(false);
+ Future<?> f = gui.cmClientAsUser(trans.getUserPrincipal(), new Retryable<Future<?>>() {
+ @Override
+ public Future<?> code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ Future<?> rv = null;
+ switch((String)trans.get(sCmd, "")) {
+ case CMArtiChangeForm.CREATE:
+ Future<Artifacts> fc;
+ rv = fc = client.create("/cert/artifacts", gui.artifactsDF, artifacts);
+ if(fc.get(AAFcli.timeout())) {
+ hgen.p("Created Artifact " + arti.getMechid() + " on " + arti.getMachine());
+ ok.set(true);
+ }
+ break;
+ case CMArtiChangeForm.UPDATE:
+ Future<Artifacts> fu = client.update("/cert/artifacts", gui.artifactsDF, artifacts);
+ if((rv=fu).get(AAFcli.timeout())) {
+ hgen.p("Artifact " + arti.getMechid() + " on " + arti.getMachine() + " is updated");
+ ok.set(true);
+ }
+ break;
+ case CMArtiChangeForm.COPY:
+ Future<Artifacts> future = client.read("/cert/artifacts/"+arti.getMechid()+'/'+arti.getMachine(), gui.artifactsDF);
+ rv = future;
+ if(future.get(AAFcli.timeout())) {
+ for(Artifact a : future.value.getArtifact()) { // only one, because these two are key
+ for(String newMachine :Split.split(',', trans.get(sOther, ""))) {
+ a.setMachine(newMachine);
+ Future<Artifacts> fup = client.update("/cert/artifacts", gui.artifactsDF, future.value);
+ if(fup.get(AAFcli.timeout())) {
+ hgen.p("Copied to " + newMachine);
+ ok.set(true);
+ }
+ }
+ }
+ }
+ break;
+ case CMArtiChangeForm.DELETE:
+ Future<Void> fv;
+ rv = fv = client.delete("/cert/artifacts/"+arti.getMechid()+"/"+arti.getMachine(),"application/json");
+ if(fv.get(AAFcli.timeout())) {
+ hgen.p("Deleted " + arti.getMechid() + " on " + arti.getMachine());
+ ok.set(true);
+ deleted.set(true);
+ }
+ break;
+ }
+ return rv;
+ }
+ });
+ if(!ok.get()) {
+ if(f==null) {
+ hgen.p("Unknown Command");
+ } else {
+ if(f.body().contains("%")) {
+ Error err = gui.getDF(Error.class).newData().in(TYPE.JSON).load(f.body()).asObject();
+ hgen.p(Vars.convert(err.getText(),err.getVariables()));
+ } else {
+ hgen.p(arti.getMechid() + " on " + arti.getMachine() + ": " + f.body());
+ }
+ }
+ }
+ hgen.br().leaf(HTMLGen.A,"class=greenbutton","href="+(deleted.get()?CMArtifactShow.HREF:CMArtiChangeForm.HREF)+
+ "?id="+arti.getMechid()+
+ "&amp;machine="+arti.getMachine() +
+ "&amp;ns="+arti.getNs())
+ .text("Back")
+ .end();
+
+ } catch (Exception e) {
+ hgen.p("Unknown Error");
+ e.printStackTrace();
+ }
+
+ }
+ hgen.br();
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeForm.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeForm.java
new file mode 100644
index 00000000..c65e7db5
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeForm.java
@@ -0,0 +1,256 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TABLE;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.org.Organization;
+import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.auth.org.OrganizationFactory;
+import org.onap.aaf.auth.org.Organization.Identity;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import certman.v1_0.Artifacts;
+import certman.v1_0.Artifacts.Artifact;
+
+public class CMArtiChangeForm extends Page {
+ private static final String COPY_ARTIFACT = "copyArtifact";
+ private static final String DELETE_ARTIFACT = "deleteArtifact";
+
+ // Package on purpose
+ static final String HREF = "/gui/artichange";
+ static final String NAME = "ArtifactChange";
+ static final String fields[] = {"id","machine","ns","directory","ca","osuser","renewal","notify","cmd","others","types[]","sans"};
+
+ static final String types[] = {"jks","file","script"};
+ static final String UPDATE = "Update";
+ static final String CREATE = "Create";
+ static final String COPY = "Copy";
+ static final String DELETE = "Delete";
+
+ public CMArtiChangeForm(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ private final Slot sID = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[0]);
+ private final Slot sMach = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[1]);
+ private final Slot sNS = gui.env.slot(CMArtiChangeForm.NAME+'.'+CMArtiChangeForm.fields[2]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ Mark js = new Mark();
+ Mark fn = new Mark();
+ hgen.js(js).function(fn,COPY_ARTIFACT)
+ .text("f=document.getElementById('"+fields[9]+"')")
+ .text("s=document.getElementById('theButton')")
+ .text("cmd=document.getElementById('"+fields[8]+"')")
+ .text("ins=document.getElementById('instruct')")
+ .text("c=document.getElementById('cbcopy')")
+ .text("trd=document.getElementById('trdelete')")
+ .li("if (c.checked==true) {" ,
+ "f.style.display=ins.style.display='block'",
+ "trd.style.display='none'",
+ "s.orig=s.value;",
+ "s.value='Copy'",
+ "cmd.setAttribute('value',s.value)",
+ "} else {",
+ "f.style.display=ins.style.display='none';",
+ "trd.style.display='block'",
+ "s.value=s.orig",
+ "cmd.setAttribute('value',s.orig)",
+ "}"
+ )
+ .end(fn)
+ .function(fn, DELETE_ARTIFACT)
+ .text("d=document.getElementById('cbdelete')")
+ .text("trc=document.getElementById('trcopy')")
+ .text("s=document.getElementById('theButton')")
+ .text("cmd=document.getElementById('"+fields[8]+"')")
+ .li("if (d.checked==true) {",
+ "s.orig=s.value;",
+ "s.value='Delete';",
+ "trc.style.display='none';",
+ "cmd.setAttribute('value',s.value);",
+ "} else {",
+ "s.value=s.orig;",
+ "trc.style.display='block';",
+ "cmd.setAttribute('value',s.orig);",
+ "}"
+ )
+ .end(js);
+
+ hgen.leaf(HTMLGen.TITLE).text("Certificate Artifact Form").end();
+ Mark form = new Mark();
+ hgen.incr(form, "form","action="+HREF,"method=post");
+
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+
+ final String incomingMach = trans.get(sMach,"");
+ String incomingNS = trans.get(sNS,"");
+ String id= trans.get(sID, "");
+ final String incomingID = id.indexOf('@')>=0?id:id+'@'+FQI.reverseDomain(incomingNS);
+
+ String submitText=UPDATE;
+ boolean delete=true;
+ try {
+ Artifact arti =gui.cmClientAsUser(trans.getUserPrincipal(), new Retryable<Artifact>() {
+ @Override
+ public Artifact code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Artifacts> fa = client.read("/cert/artifacts/"+incomingID+'/'+incomingMach, gui.artifactsDF);
+ if(fa.get(AAFcli.timeout())) {
+ for(Artifact arti : fa.value.getArtifact()) {
+ return arti; // just need the first one
+ }
+ }
+ return null;
+ }
+ });
+ if(arti==null) {
+ Organization org = OrganizationFactory.get(trans);
+ Identity user = org.getIdentity(trans, incomingID);
+ if(user==null) {
+ hgen.p("The mechID you typed, \"" + incomingID + "\", is not a valid " + org.getName() + " ID");
+ return;
+ }
+ arti = new Artifact();
+ arti.setMechid(incomingID);
+ Identity managedBy = user.responsibleTo();
+ if(managedBy == null) {
+ arti.setSponsor("Unknown Sponsor");
+ } else {
+ arti.setSponsor(managedBy.fullID());
+ }
+ arti.setMachine(incomingMach);
+ arti.setNs(incomingNS);
+ arti.setDir("");
+ arti.setCa("aaf");
+ arti.setOsUser("");
+ arti.setRenewDays(30);
+ arti.setNotification("mailto:"+user.email());
+ arti.getType().add(types[0]);
+ arti.getType().add(types[2]);
+ submitText = CREATE;
+ delete = false;
+ } else {
+ if(arti.getNotification()==null) {
+ Organization org = OrganizationFactory.get(trans);
+ Identity user = org.getIdentity(trans, incomingID);
+ arti.setNotification("mailto:"+user.email());
+ }
+ }
+ // CSO Approval no longer required for SAN use
+// final String mechID = arti.getMechid();
+// boolean maySans=gui.lur.fish(new Principal() {
+// @Override
+// public String getName() {
+// return mechID;
+// }},getPerm(arti.getCa(),"san"));
+// if(!maySans) {
+// arti.getSans().clear();
+// }
+ Mark table = new Mark(TABLE);
+ hgen.incr(table)
+ .input(fields[0],"MechID*",true,"value="+arti.getMechid())
+ .input("sponsor", "Sponsor",false,"value="+arti.getSponsor(),"readonly","style=border:none;background-color:white;")
+ .input(fields[1],"Machine*",true,"value="+arti.getMachine(),"style=width:130%;");
+// if(maySans) {
+ hgen.incr(HTMLGen.TR).incr(HTMLGen.TD).end()
+ .incr(HTMLGen.TD,"class=subtext").text("Use full machine names, ");
+ if(!trans.fish(getPerm(arti.getCa(),"ip"))) {
+ hgen.text("NO ");
+ }
+ StringBuilder sb = null;
+ for(String s: arti.getSans()) {
+ if(sb==null) {
+ sb = new StringBuilder();
+ } else {
+ sb.append(", ");
+ }
+ sb.append(s);
+ }
+
+ hgen.text("IPs allowed, separated by commas.").end()
+ .input(fields[11], "SANs", false, "value="+(sb==null?"":sb.toString()),"style=width:180%;");
+// }
+ hgen.input(fields[2],"Namespace",true,"value="+arti.getNs(),"style=width:180%;")
+ .input(fields[3],"Directory", true, "value="+arti.getDir(),"style=width:180%;")
+ .input(fields[4],"Certificate Authority",true,"value="+arti.getCa(),"style=width:180%;")
+ .input(fields[5],"O/S User",true,"value="+arti.getOsUser())
+ .input(fields[6],"Renewal Days before Expiration", true, "value="+arti.getRenewDays(),"style=width:20%;")
+ .input(fields[7],"Notification",true,"value="+arti.getNotification())
+ .incr(HTMLGen.TR)
+ .incr(HTMLGen.TD).leaf("label","for=types","required").text("Artifact Types").end(2)
+ .incr(HTMLGen.TD);
+ for(int i=0;i<types.length;++i) {
+ hgen.leaf("input","type=checkbox","name=types."+i,arti.getType().contains(types[i])?"checked":"").text(types[i]).end().br();
+ }
+
+ Mark tr = new Mark();
+ hgen.incr(tr,HTMLGen.TR).incr(HTMLGen.TD,"id=trcopy")
+ .leaf("input","id=cbcopy","type=checkbox","onclick="+COPY_ARTIFACT+"()").text("Copy Artifact").end(2)
+ .incr(HTMLGen.TD,"id=tdcopy","style:display:none;")
+ .incr("label","id=instruct","style=font-style:italic;font-size:80%;display:none;")
+ .text("Add full machine names, separated by commas.").end()
+ .tagOnly("input","id="+fields[9],"name="+fields[9],"style=display:none;width:150%;").end(2)
+ .end(tr);
+ hgen.incr(tr,HTMLGen.TR,"id=trdelete").incr(HTMLGen.TD,"id=tddelete")
+ .leaf("input","id=cbdelete","type=checkbox","onclick="+DELETE_ARTIFACT+"()",delete?"style:display:none;":"").text("Delete Artifact").end(2)
+ .end(tr);
+ hgen.end(table);
+
+ hgen.tagOnly("input","id="+fields[8],"name="+fields[8],"value="+submitText,"style=display:none;");
+ hgen.tagOnly("input","id=theButton","type=submit", "orig="+submitText,"value="+submitText);
+
+ } catch(CadiException | LocatorException | OrganizationException e) {
+ throw new APIException(e);
+ }
+ }
+
+ });
+ hgen.end(form);
+ }
+ });
+
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java
new file mode 100644
index 00000000..0ad73649
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java
@@ -0,0 +1,251 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.ConnectException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.SlotCode;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Chrono;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import certman.v1_0.Artifacts;
+import certman.v1_0.Artifacts.Artifact;
+import certman.v1_0.CertInfo;
+
+public class CMArtifactShow extends Page {
+
+ public static final String HREF = "/gui/cmarti";
+ public static final String NAME = "ArtifactsShow";
+ private static ArtiTable arti;
+ public static SlotCode<AuthzTrans> slotCode;
+ private enum Params{id,ns};
+
+
+ public CMArtifactShow(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, Params.values() ,
+ new BreadCrumbs(breadcrumbs),
+ arti = new ArtiTable(gui.env)
+ );
+ // Setting so we can get access to HTMLGen clone and Slots
+ arti.set(this,slotCode);
+ }
+
+ private static class ArtiTable extends Table<AAF_GUI, AuthzTrans> {
+ private static Model model;
+ private SlotCode<AuthzTrans> sc;
+ enum Params {id,ns};
+ public ArtiTable(AuthzEnv env) {
+ super((String)null,env.newTransNoAvg(),model = new Model(),
+ slotCode = new SlotCode<AuthzTrans>(false,env,NAME,Params.values()) {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ Mark js = new Mark();
+ hgen.js(js).function("newArtifact")
+ .text("machine=document.getElementById('machine');")
+ .text("window.open('"
+ +CMArtiChangeForm.HREF+
+ "?id="+get(trans, Params.id,"")+
+ "&ns="+get(trans, Params.ns,"")+
+ "&machine='+machine.value,'_self');"
+ ).end(js);
+ hgen.leaf("input","id=machine","style=margin:1em 1em 1em 1em;width:30%").end();
+ hgen.leaf(HTMLGen.A,"class=greenbutton","href=javascript:newArtifact()","style=color:white;").text("New Machine").end();
+ }
+ });
+ }
+ },"class=std");
+ }
+
+
+ public void set(CMArtifactShow cmArtifactShow, SlotCode<AuthzTrans> sc) {
+ this.sc = sc;
+ model.set(cmArtifactShow,sc);
+ }
+
+ @Override
+ protected String title(AuthzTrans trans) {
+ StringBuilder sb = new StringBuilder("X509 Certificates");
+ if(sc!=null) { // initialized
+ sb.append(" for ");
+ String id = sc.get(trans,Params.id,"");
+ sb.append(id);
+ if(id.indexOf('@')<0) {
+ sb.append('@');
+ sb.append(FQI.reverseDomain(sc.get(trans, Params.ns,"missingDomain")));
+ }
+ }
+ return sb.toString();
+ }
+ }
+ /**
+ * Implement the table content for Cred Detail
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model implements Table.Data<AAF_GUI,AuthzTrans> {
+ private CMArtifactShow cas;
+ private SlotCode<AuthzTrans> sc;
+
+ // Covering for Constructor Order
+ private void set(CMArtifactShow cas, SlotCode<AuthzTrans> sc) {
+ this.cas = cas;
+ this.sc = sc;
+ }
+
+ private static final String[] headers = new String[]{"Machine","Directory","CA","Renews","Expires",""};
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ String str = sc.get(trans,Params.id, null);
+ if(str==null) {
+ return Cells.EMPTY;
+ }
+ final String id = str.indexOf('@')>=0?str:str + '@' + FQI.reverseDomain(sc.get(trans,Params.ns, ""));
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ final TimeTaken tt = trans.start("AAF X509 Details",Env.REMOTE);
+ try {
+ gui.cmClientAsUser(trans.getUserPrincipal(),new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<CertInfo> fuCI = client.read("/cert/id/"+id,gui.certInfoDF);
+ Future<Artifacts> fuArt = client.read("/cert/artifacts?mechid="+id, gui.artifactsDF);
+
+ X509Certificate[] lc;
+ if(fuCI.get(AAFcli.timeout())) {
+ TimeTaken tt1 = trans.start("x509Certificate", Env.SUB);
+ try {
+ Collection<? extends Certificate> xcs = Factory.toX509Certificate(fuCI.value.getCerts());
+ lc = new X509Certificate[xcs.size()];
+ xcs.toArray(lc);
+ } catch (CertificateException e) {
+ trans.error().log(e,"Bad Certificate entry");
+ throw new CadiException(e);
+ } finally {
+ tt1.done();
+ }
+ } else {
+ lc = null;
+ trans.error().log("Cannot retrieve Certificates for " + id);
+ }
+ if(fuArt.get(AAFcli.timeout())) {
+ for(Artifact arti : fuArt.value.getArtifact()) {
+ StringWriter sw = new StringWriter();
+ HTMLGen hgen = cas.clone(sw);
+ Mark mark = new Mark();
+ hgen.leaf(HTMLGen.A,"class=button",
+ "href="+CMArtiChangeForm.HREF+"?id="+arti.getMechid() +"&machine="+arti.getMachine()+"&ns="+arti.getNs())
+ .text("Details")
+ .end(mark);
+ Date last = null;
+ if(lc!=null) {
+ for(X509Certificate xc : lc) {
+ if(xc.getSubjectDN().getName().contains("CN="+arti.getMachine())) {
+ if(last==null || last.before(xc.getNotAfter())) {
+ last = xc.getNotAfter();
+ }
+ }
+ }
+ }
+ GregorianCalendar renew;
+ if(last!=null) {
+ renew = new GregorianCalendar();
+ renew.setTime(last);
+ renew.add(GregorianCalendar.DAY_OF_MONTH,arti.getRenewDays()*-1);
+ } else {
+ renew = null;
+ }
+
+ rv.add(new AbsCell[] {
+ new TextCell(arti.getMachine(),"style=width:20%;"),
+ new TextCell(arti.getDir(),"style=width:25%;"),
+ new TextCell(arti.getCa(),"style=width:2%;text-align:center;"),
+ new TextCell(renew==null?
+ arti.getRenewDays().toString() + " days before Exp":
+ Chrono.dateOnlyStamp(renew),"style=width:6%;text-align:center;"),
+ new TextCell(last==null?"None Deployed":Chrono.dateOnlyStamp(last),"style=width:5%;text-align:center;"),
+ new TextCell(sw.toString(),"style=width:10%;text-align:center;")
+ });
+ }
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***")});
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,null);
+ }
+
+ @Override
+ public void prefix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ }
+
+ @Override
+ public void postfix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ }
+
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java
new file mode 100644
index 00000000..8c7c8763
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java
@@ -0,0 +1,352 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.SlotCode;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Chrono;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Users;
+import aaf.v2_0.Users.User;
+import certman.v1_0.Artifacts;
+import certman.v1_0.Artifacts.Artifact;
+
+public class CredDetail extends Page {
+
+ public static final String HREF = "/gui/creddetail";
+ public static final String NAME = "CredDetail";
+ private static Model model;
+ private static SlotCode<AuthzTrans> slotCode;
+ enum Params {id,ns};
+
+
+ public CredDetail(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, Params.values(),
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Cred Details",gui.env.newTransNoAvg(),model = new Model(),
+ slotCode = new SlotCode<AuthzTrans>(false,gui.env,NAME,Params.values()) {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String ns = get(trans, Params.ns,"");
+ String domain = FQI.reverseDomain(ns);
+ Mark js = new Mark(), fn=new Mark();
+ hgen.js(js).function(fn,"newArtifact")
+ .text("id=document.getElementById('id');")
+ .text("if(id.value=='') {alert('Enter the id in box');} else {")
+ .text("window.open('"+CMArtiChangeForm.HREF+"?id='+id.value+'&ns="+ns+"','_self');}"
+ )
+ .end(fn)
+ .function("newPassword")
+ .text("id=document.getElementById('id');")
+ .text("if(id.value=='') {alert('Enter the id in box');} else {")
+ .text("window.open('"+PassChangeForm.HREF+"?id='+id.value+'@"+domain+"&ns="+ns+"','_self');}"
+ )
+ .end(js);
+ hgen.leaf("i","style=margin:1em 0em 1em 1em;").text("ID:").end()
+ .leaf("input","id=id","style=width:10%;").end().text("@").text(domain).br()
+ .leaf(HTMLGen.A,"class=greenbutton","href=javascript:newArtifact()","style=color:white;margin:1.2em 0em 1em 1em;").text("As Cert Artifact").end()
+ .leaf(HTMLGen.A,"class=greenbutton","href=javascript:newPassword()","style=color:white;margin:1.2em 0em 1em 1em;").text("w/Password").end()
+ ;
+ }
+ });
+ }
+ },"class=std")
+
+ );
+ // Setting so we can get access to HTMLGen clone
+ model.set(this,slotCode);
+ }
+
+
+
+ /**
+ * Implement the table content for Cred Detail
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String STYLE_WIDTH_5 = "style=width:5%;";
+ private static final String STYLE_WIDTH_10 = "style=width:10%;";
+ private static final String STYLE_WIDTH_15 = "style=width:15%;";
+ private static final String STYLE_WIDTH_20 = "style=width:20%;";
+ private static final String STYLE_WIDTH_70 = "style=width:70%;";
+ private SlotCode<AuthzTrans> sc;
+ private CredDetail cd;
+ // Covering for Constructor Order
+ private void set(CredDetail credDetail, SlotCode<AuthzTrans> slotCode) {
+ cd = credDetail;
+ sc = slotCode;
+ }
+
+ @Override
+ public void prefix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String ns = sc.get(trans, Params.ns, "");
+ final String id = sc.get(trans, Params.id, "");
+ if(ns==null) {
+ return Cells.EMPTY;
+ }
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ final TimeTaken tt = trans.start("AAF Cred Details",Env.REMOTE);
+ List<Artifact> la;
+ try {
+ la = gui.cmClientAsUser(trans.getUserPrincipal(), new Retryable<List<Artifact>>() {
+ @Override
+ public List<Artifact> code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ Future<Artifacts> fa = client.read("/cert/artifacts?ns="+ns,gui.artifactsDF);
+ if(fa.get(AAFcli.timeout())) {
+ return fa.value.getArtifact();
+ } else {
+ return null;
+ }
+ }
+
+ });
+ final Set<String> lns = new HashSet<String>();
+ if(la!=null) {
+ for(Artifact a : la){
+ lns.add(a.getMechid());
+ }
+ }
+ gui.clientAsUser(trans.getUserPrincipal(),new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Users> fu = client.read("/authn/creds/ns/"+ns,gui.getDF(Users.class));
+ if(fu.get(AAFcli.timeout())) {
+ // Organize User entries
+ Map<String,List<Map<Integer,List<User>>>> users = new HashMap<String,List<Map<Integer,List<User>>>>();
+
+ List<Map<Integer,List<User>>> lmu=null;
+ Map<Integer, List<User>> mu = null;
+ List<User> lu = null;
+
+ for (User u : fu.value.getUser()) {
+ if(u.getType() == 200) {
+ lns.remove(u.getId());
+ }
+ lmu = users.get(u.getId());
+ if(lmu==null) {
+ users.put(u.getId(),lmu=new ArrayList<Map<Integer,List<User>>>());
+ }
+ mu=null;
+ for(Map<Integer,List<User>> xmu : lmu) {
+ if(xmu.containsKey(u.getType())) {
+ mu = xmu;
+ }
+ }
+
+ if(mu==null) {
+ lmu.add(mu=new HashMap<Integer,List<User>>());
+ }
+
+ lu = mu.get(u.getType());
+ if(lu==null) {
+ mu.put(u.getType(),lu = new ArrayList<User>());
+ }
+ lu.add(u);
+ }
+
+ int count=0;
+ for (Entry<String, List<Map<Integer, List<User>>>> ulm : users.entrySet()) {
+ String key = "cred_"+count++;
+ StringWriter buttons = new StringWriter();
+ HTMLGen hgen = cd.clone(buttons);
+ hgen.leaf("button","onclick=divVisibility('"+key+"');","class=button").text("Expand").end();
+
+ StringWriter creds = new StringWriter();
+ hgen = cd.clone(creds);
+ Mark div = hgen.divID(key,ulm.getKey().equals(id)?"":"style=display:none;");
+ for(Map<Integer, List<User>> miu : ulm.getValue()) {
+ Mark utable = new Mark();
+ hgen.leaf(utable,HTMLGen.TABLE);
+
+ Mark uRow = new Mark();
+ String cls;
+ boolean first = true;
+
+ for( Entry<Integer, List<User>> es : miu.entrySet()) {
+ Collections.sort(es.getValue(),new Comparator<User>() {
+ @Override
+ public int compare(User u1, User u2) {
+ int rv = u1.getType().compareTo(u2.getType());
+ return rv==0?u2.getExpires().compare(u1.getExpires()):rv;
+ }
+ });
+ int xcnt = 0;
+ XMLGregorianCalendar oldest=null, newest=null;
+ String id = null;
+ for(User u: es.getValue()) {
+ if(id==null) {
+ id = u.getId();
+ }
+ // Need to compile entries for Certificates on this screen
+ if(es.getKey()==200) {
+ ++xcnt;
+ if(oldest==null || oldest.compare(u.getExpires())<0) {
+ oldest = u.getExpires();
+ }
+ if(newest==null || newest.compare(u.getExpires())<0) {
+ newest = u.getExpires();
+ }
+ } else {
+ hgen.leaf(uRow,HTMLGen.TR);
+ if(first) {
+ hgen.leaf(HTMLGen.TD,cls="class=detailFirst",STYLE_WIDTH_10);
+ switch(es.getKey()) {
+ case 1:
+ case 2: hgen.text("Password");
+ break;
+ case 10: hgen.text("Certificate"); break;
+ }
+ } else {
+ hgen.leaf(HTMLGen.TD,cls="class=detail",STYLE_WIDTH_10+"text-align:center;").text("\"");
+ }
+ hgen.end();
+ hgen.incr(HTMLGen.TD,cls,STYLE_WIDTH_20);
+
+ hgen.leaf(HTMLGen.A,
+ "class=button",
+ "href="+PassDeleteAction.HREF+
+ "?id="+id+
+ "&amp;ns="+ns+
+ "&amp;date="+u.getExpires().toXMLFormat() +
+ "&amp;type="+u.getType())
+ .text("Delete").end();
+ if(first && es.getKey()<10) { // Change Password Screen
+ hgen.leaf(HTMLGen.A,"class=button","href="+PassChangeForm.HREF+"?id="+id+"&amp;ns="+ns)
+ .text("Add")
+ .end();
+ }
+ first=false;
+ hgen.end().leaf(HTMLGen.TD,cls,STYLE_WIDTH_70)
+ .text(Chrono.niceDateStamp(u.getExpires()))
+ .end();
+
+ hgen.end(uRow);
+ }
+ }
+ if(xcnt>0) { // print compilations, if any, of Certificate
+ hgen.leaf(uRow,HTMLGen.TR)
+ .leaf(HTMLGen.TD,cls="class=detailFirst",STYLE_WIDTH_10).text("x509").end()
+ .leaf(HTMLGen.TD, cls,STYLE_WIDTH_20)
+ .leaf(HTMLGen.A,"class=button","href="+CMArtifactShow.HREF+"?id="+id+"&amp;ns="+ns)
+ .text("View All")
+ .end(2)
+ .leaf(HTMLGen.TD, cls,STYLE_WIDTH_70).text(String.format(
+ xcnt>0?"%d Certificate%s, ranging from %s to %s"
+ :"%d Certificate%s",
+ xcnt,
+ xcnt==1?"":"s",
+ Chrono.niceDateStamp(oldest),
+ Chrono.niceDateStamp(newest)))
+ .end(uRow);
+
+ }
+ }
+ hgen.end(utable);
+ }
+
+ hgen.end(div);
+
+ rv.add(new AbsCell[] {
+ new TextCell(ulm.getKey(),STYLE_WIDTH_15),
+ new TextCell(buttons.toString(),STYLE_WIDTH_5),
+ new TextCell(creds.toString(),STYLE_WIDTH_70)
+ });
+ }
+ for(String missing : lns) {
+ StringWriter buttons = new StringWriter();
+ HTMLGen hgen = cd.clone(buttons);
+ hgen.leaf(HTMLGen.A,"class=button","href="+CMArtifactShow.HREF+"?id="+missing+"&amp;ns="+ns)
+ .text("View All")
+ .end(2);
+ rv.add(new AbsCell[] {
+ new TextCell(missing,STYLE_WIDTH_15),
+ new TextCell(buttons.toString(),STYLE_WIDTH_5),
+ new TextCell("No X509 Credential Instantiated")
+ });
+ }
+
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***")});
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,null);
+ }
+
+ @Override
+ public void postfix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ }
+
+
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java
new file mode 100644
index 00000000..caad42b5
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.A;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.H3;
+
+import java.io.IOException;
+
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+
+public class Home extends Page {
+ public static final String HREF = "/gui/home";
+ public Home(final AAF_GUI gui) throws APIException, IOException {
+ super(gui.env,"Home",HREF, NO_FIELDS, new NamedCode(false,"content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen xgen) throws APIException, IOException {
+// // TEMP
+// JSGen jsg = xgen.js();
+// jsg.function("httpPost","sURL","sParam")
+// .text("var oURL = new java.net.URL(sURL)")
+// .text("var oConn = oURL.openConnection();")
+// .text("oConn.setDoInput(true);")
+// .text("oConn.setDoOutpu(true);")
+// .text("oConn.setUseCaches(false);")
+// .text("oConn.setRequestProperty(\"Content-Type\",\"application/x-www-form-urlencoded\");")
+// .text(text)
+// jsg.done();
+ // TEMP
+ final Mark pages = xgen.divID("Pages");
+ xgen.leaf(H3).text("Choose from the following:").end()
+ .leaf(A,"href=myperms").text("My Permissions").end()
+ .leaf(A,"href=myroles").text("My Roles").end()
+ // TODO: uncomment when on cassandra 2.1.2 for MyNamespace GUI page
+ .leaf(A,"href=ns").text("My Namespaces").end()
+ .leaf(A,"href=approve").text("My Approvals").end()
+ .leaf(A, "href=myrequests").text("My Pending Requests").end()
+ // Enable later
+// .leaf(A, "href=onboard").text("Onboarding").end()
+ // Password Change. If logged in as CSP/GSO, go to their page
+ .leaf(A,"href=passwd").text("Password Management").end()
+ .leaf(A,"href=cui").text("Command Prompt").end()
+ .leaf(A,"href=api").text("AAF API").end()
+ ;
+
+ xgen.end(pages);
+ }
+ });
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLanding.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLanding.java
new file mode 100644
index 00000000..7dcc65aa
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLanding.java
@@ -0,0 +1,115 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.URLDecoder;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class LoginLanding extends Page {
+ public static final String HREF = "/login";
+ static final String NAME = "Login";
+ static final String fields[] = {"id","password","environment"};
+ static final String envs[] = {"DEV","TEST","PROD"};
+
+ public LoginLanding(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME,HREF, fields, new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ hgen.leaf("p").text("No login credentials are found in your current session. " +
+ "Choose your preferred login option to continue.").end();
+
+ Mark loginPaths = hgen.divID("Pages");
+
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI authGUI, AuthzTrans trans, Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException {
+ HttpServletRequest req = trans.get(gui.slot_httpServletRequest, null);
+ if(req!=null) {
+ String query = req.getQueryString();
+ if(query!=null) {
+ for(String qs : query.split("&")) {
+ int equals = qs.indexOf('=');
+ xgen.leaf(HTMLGen.A, "href="+URLDecoder.decode(qs.substring(equals+1),Config.UTF_8)).text(qs.substring(0,equals).replace('_', ' ')).end();
+ }
+ }
+ }
+ xgen.leaf(HTMLGen.A, "href=gui/home?Authentication=BasicAuth").text("AAF Basic Auth").end();
+ }
+ });
+// hgen.leaf("a", "href=#","onclick=divVisibility('cso');").text("Global Login").end()
+// .incr("p", "id=cso","style=display:none").text("this will redirect to global login").end()
+// .leaf("a", "href=#","onclick=divVisibility('tguard');").text("tGuard").end()
+// .incr("p", "id=tguard","style=display:none").text("this will redirect to tGuard login").end()
+// hgen.leaf("a", "href=#","onclick=divVisibility('basicauth');").text("AAF Basic Auth").end();
+ hgen.end(loginPaths);
+
+// hgen.incr("form","method=post","style=display:none","id=basicauth","gui/home?Authentication=BasicAuth");
+// Mark table = new Mark(TABLE);
+// hgen.incr(table);
+// cache.dynamic(hgen, new DynamicCode<HTMLGen, AuthGUI, AuthzTrans>() {
+// @Override
+// public void code(final AuthGUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen)
+// throws APIException, IOException {
+// hgen
+// .input(fields[0],"Username",true)
+// .input(fields[1],"Password",true, "type=password");
+// Mark selectRow = new Mark();
+// hgen
+// .incr(selectRow, "tr")
+// .incr("td")
+// .incr("label", "for=envs", "required").text("Environment").end()
+// .end()
+// .incr("td")
+// .incr("select", "name=envs", "id=envs", "required")
+// .incr("option", "value=").text("Select Environment").end();
+// for (String env : envs) {
+// hgen.incr("option", "value="+env).text(env).end();
+// }
+// hgen
+// .end(selectRow)
+
+// hgen.end();
+// }
+// });
+// hgen.end();
+// hgen.tagOnly("input", "type=submit", "value=Submit")
+// .tagOnly("input", "type=reset", "value=Reset")
+// .end();
+
+
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLandingAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLandingAction.java
new file mode 100644
index 00000000..9ab3fa71
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/LoginLandingAction.java
@@ -0,0 +1,65 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class LoginLandingAction extends Page {
+ public LoginLandingAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,"Login",LoginLanding.HREF, LoginLanding.fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sID = gui.env.slot(LoginLanding.NAME+'.'+LoginLanding.fields[0]);
+// final Slot sPassword = gui.env.slot(LoginLanding.NAME+'.'+LoginLanding.fields[1]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String username = trans.get(sID,null);
+// String password = trans.get(sPassword,null);
+
+ hgen.p("User: "+username);
+ hgen.p("Pass: ********");
+
+ // TODO: clarification from JG
+ // put in request header?
+ // then pass through authn/basicAuth call?
+
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java
new file mode 100644
index 00000000..5df050bf
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java
@@ -0,0 +1,247 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.auth.validation.Validator;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Nss;
+import aaf.v2_0.Nss.Ns;
+import aaf.v2_0.Perm;
+import aaf.v2_0.Perms;
+import aaf.v2_0.Role;
+import aaf.v2_0.Roles;
+
+public class NsDetail extends Page {
+
+ public static final String HREF = "/gui/nsdetail";
+ public static final String NAME = "NsDetail";
+ static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id=";
+ public static enum NS_FIELD { OWNERS, ADMINS, ROLES, PERMISSIONS, CREDS};
+ private static final String BLANK = "";
+ private static Slot keySlot;
+ private static Model model;
+ private static String gw_url;
+
+
+ public NsDetail(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, new String[] {"ns"},
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Namespace Details",gui.env.newTransNoAvg(),model=new Model(),"class=detail")
+ );
+ model.set(this);
+ keySlot = gui.env.slot(NAME+".ns");
+ gw_url = gui.env.getProperty(Config.GW_URL);
+ if(gw_url==null) {
+ gw_url="";
+ } else {
+ gw_url+="/aaf/2.0";
+ }
+ }
+
+ /**
+ * Implement the table content for Namespace Detail
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String CSP_ATT_COM = "@csp.att.com";
+ private NsDetail nd;
+
+ public void set(NsDetail nsDetail) {
+ nd=nsDetail;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String nsName = trans.get(keySlot, null);
+ Validator v = new Validator();
+ v.ns(nsName);
+ if(v.err()) {
+ trans.warn().printf("Error in NsDetail Request: %s", v.errs());
+ return Cells.EMPTY;
+ }
+
+ if(nsName==null) {
+ return Cells.EMPTY;
+ }
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ rv.add(new AbsCell[]{new TextCell("Name:"),new TextCell(nsName)});
+
+ final TimeTaken tt = trans.start("AAF Namespace Details",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(),new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Nss> fn = client.read("/authz/nss/"+nsName,gui.getDF(Nss.class));
+
+ if(fn.get(AAF_GUI.TIMEOUT)) {
+ tt.done();
+ try {
+// TimeTaken tt = trans.start("Load Data", Env.SUB);
+
+ for(Ns n : fn.value.getNs()) {
+ String desc = (n.getDescription()!=null?n.getDescription():BLANK);
+ rv.add(new AbsCell[]{new TextCell("Description:"),new TextCell(desc)});
+
+ addField(trans, nsName, rv, n.getAdmin(), NS_FIELD.ADMINS);
+ addField(trans, nsName, rv, n.getResponsible(), NS_FIELD.OWNERS);
+
+ StringWriter sw = new StringWriter();
+ HTMLGen hgen = nd.clone(sw);
+ hgen.leaf(HTMLGen.A, "class=greenbutton","href="+CredDetail.HREF+"?ns="+nsName).text("Cred Details").end();
+ rv.add(new AbsCell[] {
+ new TextCell("Credentials"),
+ new TextCell(sw.toString())
+ });
+
+
+ Future<Roles> fr = client.read(
+ "/authz/roles/ns/"+nsName,
+ gui.getDF(Roles.class)
+ );
+ List<String> roles = new ArrayList<String>();
+ if(fr.get(AAFcli.timeout())) {
+ for (Role r : fr.value.getRole()) {
+ roles.add(r.getName());
+ }
+ }
+ addField(trans, nsName, rv, roles, NS_FIELD.ROLES);
+
+
+ Future<Perms> fp = client.read(
+ "/authz/perms/ns/"+nsName,
+ gui.getDF(Perms.class)
+ );
+ List<String> perms = new ArrayList<String>();
+
+ if(fp.get(AAFcli.timeout())) {
+ for (Perm p : fp.value.getPerm()) {
+ perms.add(p.getType() + "|" + p.getInstance() + "|" + p.getAction());
+ }
+ }
+ addField(trans, nsName, rv, perms, NS_FIELD.PERMISSIONS);
+ }
+ String historyLink = NsHistory.HREF
+ + "?name=" + nsName;
+ rv.add(new AbsCell[] {new RefCell("See History",historyLink,false)});
+ } finally {
+ tt.done();
+ }
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***")});
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,null);
+ }
+
+ private void addField(AuthzTrans trans, String ns, List<AbsCell[]> rv, List<String> values, NS_FIELD field) {
+ if (!values.isEmpty()) {
+ switch(field) {
+ case OWNERS:
+ case ADMINS:
+ case CREDS:
+ for (int i=0; i< values.size(); i++) {
+ AbsCell label = (i==0?new TextCell(sentenceCase(field)+":"):AbsCell.Null);
+ String user = values.get(i);
+ AbsCell userCell = (user.endsWith(CSP_ATT_COM)?
+ new RefCell(user,WEBPHONE + user.substring(0,user.indexOf('@')),true):new TextCell(user));
+ rv.add(new AbsCell[] {
+ label,
+ userCell
+ });
+ }
+ break;
+ case ROLES:
+ for (int i=0; i< values.size(); i++) {
+ String role = values.get(i);
+ AbsCell label = (i==0?new TextCell(sentenceCase(field)+":"):AbsCell.Null);
+ rv.add(new AbsCell[] {
+ label,
+ new RefCell(role,RoleDetail.HREF+"?role="+role+"&ns="+ns,false)
+ });
+ }
+ break;
+ case PERMISSIONS:
+ for (int i=0; i< values.size(); i++) {
+ AbsCell label = (i==0?new TextCell(sentenceCase(field)+":","style=width:20%"):AbsCell.Null);
+ String perm = values.get(i);
+ String[] fields = perm.split("\\|");
+ String grantLink = gw_url
+ + PermGrantForm.HREF
+ + "?type=" + fields[0].trim()
+ + "&amp;instance=" + fields[1].trim()
+ + "&amp;action=" + fields[2].trim();
+
+ rv.add(new AbsCell[] {
+ label,
+ new TextCell(perm,"style=width:60%;"),
+ new RefCell("Grant", grantLink,false,"class=button","style=width:20%;")
+ });
+ }
+ break;
+ }
+
+ }
+ }
+
+ private String sentenceCase(NS_FIELD field) {
+ String sField = field.toString();
+ return sField.substring(0, 1).toUpperCase() + sField.substring(1).toLowerCase();
+ }
+
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java
new file mode 100644
index 00000000..414f992f
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java
@@ -0,0 +1,230 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.History;
+import aaf.v2_0.History.Item;
+
+public class NsHistory extends Page {
+ static final String NAME="NsHistory";
+ static final String HREF = "/gui/nsHistory";
+ static final String FIELDS[] = {"name","dates"};
+ static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id=";
+ static enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,
+ AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
+
+ public NsHistory(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("History", gui.env.newTransNoAvg(),new Model(gui.env),"class=std"),
+ new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final Slot name = gui.env.slot(NAME+".name");
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String obName = trans.get(name, null);
+
+ // Use Javascript to make the table title more descriptive
+ hgen.js()
+ .text("var caption = document.querySelector(\".title\");")
+ .text("caption.innerHTML='History for Namespace [ " + obName + " ]';")
+ .done();
+
+ // Use Javascript to change Link Target to our last visited Detail page
+ String lastPage = NsDetail.HREF + "?name=" + obName;
+ hgen.js()
+ .text("alterLink('nsdetail', '"+lastPage + "');")
+ .done();
+
+ hgen.br();
+ hgen.leaf("a","href=#advanced_search","onclick=divVisibility('advanced_search');").text("Advanced Search").end()
+ .divID("advanced_search", "style=display:none");
+ hgen.incr("table");
+
+ addDateRow(hgen,"Start Date");
+ addDateRow(hgen,"End Date");
+ hgen.incr("tr").incr("td");
+ hgen.tagOnly("input", "type=button","value=Get History",
+ "onclick=datesURL('"+HREF+"?name=" + obName+"');");
+ hgen.end().end();
+ hgen.end();
+ hgen.end();
+
+ }
+ });
+ }
+ }
+
+ );
+ }
+
+ private static void addDateRow(HTMLGen hgen, String s) {
+ hgen
+ .incr("tr")
+ .incr("td")
+ .incr("label", "for=month", "required").text(s+"*").end()
+ .end()
+ .incr("td")
+ .incr("select", "name=month"+s.substring(0, s.indexOf(' ')), "id=month"+s.substring(0, s.indexOf(' ')), "required")
+ .incr("option", "value=").text("Month").end();
+ for (Month m : Month.values()) {
+ if (Calendar.getInstance().get(Calendar.MONTH) == m.ordinal()) {
+ hgen.incr("option", "selected", "value="+(m.ordinal()+1)).text(m.name()).end();
+ } else {
+ hgen.incr("option", "value="+(m.ordinal()+1)).text(m.name()).end();
+ }
+ }
+ hgen.end()
+ .end()
+ .incr("td")
+ .tagOnly("input","type=number","id=year"+s.substring(0, s.indexOf(' ')),"required",
+ "value="+Calendar.getInstance().get(Calendar.YEAR), "min=1900",
+ "max="+Calendar.getInstance().get(Calendar.YEAR),
+ "placeholder=Year").end()
+ .end();
+ }
+
+
+
+
+ /**
+ * Implement the Table Content for History
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String CSP_ATT_COM = "@csp.att.com";
+ private static final String[] headers = new String[] {"Date","User","Memo"};
+ private Slot name;
+ private Slot dates;
+
+ public Model(AuthzEnv env) {
+ name = env.slot(NAME+".name");
+ dates = env.slot(NAME+".dates");
+ }
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String oName = trans.get(name,null);
+ final String oDates = trans.get(dates,null);
+
+ if(oName==null) {
+ return Cells.EMPTY;
+ }
+
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ String msg = null;
+ final TimeTaken tt = trans.start("AAF Get History for Namespace ["+oName+"]",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ if (oDates != null) {
+ client.setQueryParams("yyyymm="+oDates);
+ }
+ Future<History> fh = client.read("/authz/hist/ns/"+oName,gui.getDF(History.class));
+ if (fh.get(AAF_GUI.TIMEOUT)) {
+ tt.done();
+ TimeTaken tt2 = trans.start("Load History Data", Env.SUB);
+ try {
+ List<Item> histItems = fh.value.getItem();
+
+ java.util.Collections.sort(histItems, new Comparator<Item>() {
+ @Override
+ public int compare(Item o1, Item o2) {
+ return o2.getTimestamp().compare(o1.getTimestamp());
+ }
+ });
+
+ for (Item i : histItems) {
+ String user = i.getUser();
+ AbsCell userCell = (user.endsWith(CSP_ATT_COM)?
+ new RefCell(user,WEBPHONE + user.substring(0,user.indexOf('@')),true):new TextCell(user));
+
+ rv.add(new AbsCell[] {
+ new TextCell(i.getTimestamp().toGregorianCalendar().getTime().toString()),
+ userCell,
+ new TextCell(i.getMemo())
+ });
+ }
+ } finally {
+ tt2.done();
+ }
+ } else {
+ if (fh.code()==403) {
+ rv.add(new AbsCell[] {new TextCell("You may not view History of Namespace [" + oName + "]", "colspan = 3", "class=center")});
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***", "colspan = 3", "class=center")});
+ }
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,msg);
+ }
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoAction.java
new file mode 100644
index 00000000..4328653e
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoAction.java
@@ -0,0 +1,158 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.text.ParseException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Chrono;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.CredRequest;
+
+public class NsInfoAction extends Page {
+ public NsInfoAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,"Onboard",PassChangeForm.HREF, PassChangeForm.fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sID = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[0]);
+ final Slot sCurrPass = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[1]);
+ final Slot sPassword = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[2]);
+ final Slot sPassword2 = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[3]);
+ final Slot startDate = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[4]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String id = trans.get(sID,null);
+ String currPass = trans.get(sCurrPass,null);
+ final String password = trans.get(sPassword,null);
+ String password2 = trans.get(sPassword2,null);
+
+ // Run Validations
+ boolean fail = true;
+
+ if (id==null || id.indexOf('@')<=0) {
+ hgen.p("Data Entry Failure: Please enter a valid ID, including domain.");
+ } else if(password == null || password2 == null || currPass == null) {
+ hgen.p("Data Entry Failure: Both Password Fields need entries.");
+ } else if(!password.equals(password2)) {
+ hgen.p("Data Entry Failure: Passwords do not match.");
+ } else { // everything else is checked by Server
+ final CredRequest cred = new CredRequest();
+ cred.setId(id);
+ cred.setPassword(currPass);
+ try {
+ fail = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("Check Current Password",Env.REMOTE);
+ try {
+ Future<CredRequest> fcr = client.create( // Note: Need "Post", because of hiding password in SSL Data
+ "/authn/validate",
+ gui.getDF(CredRequest.class),
+ cred
+ );
+ boolean go;
+ boolean fail = true;
+ fcr.get(5000);
+ if(fcr.code() == 200) {
+ hgen.p("Current Password validated");
+ go = true;
+ } else {
+ hgen.p(String.format("Invalid Current Password: %d %s",fcr.code(),fcr.body()));
+ go = false;
+ }
+ if(go) {
+ tt.done();
+ tt = trans.start("AAF Change Password",Env.REMOTE);
+ try {
+ // Change over Cred to reset mode
+ cred.setPassword(password);
+ String start = trans.get(startDate, null);
+ if(start!=null) {
+ try {
+ cred.setStart(Chrono.timeStamp(Chrono.dateOnlyFmt.parse(start)));
+ } catch (ParseException e) {
+ throw new CadiException(e);
+ }
+ }
+
+ fcr = client.create(
+ "/authn/cred",
+ gui.getDF(CredRequest.class),
+ cred
+ );
+
+ if(fcr.get(5000)) {
+ // Do Remote Call
+ hgen.p("New Password has been added.");
+ fail = false;
+ } else {
+ gui.writeError(trans, fcr, hgen, 0);
+ }
+ } finally {
+ tt.done();
+ }
+ }
+ return fail;
+ } finally {
+ tt.done();
+ }
+ }
+ });
+
+ } catch (Exception e) {
+ hgen.p("Unknown Error");
+ e.printStackTrace();
+ }
+ }
+ hgen.br();
+ if(fail) {
+ hgen.incr("a",true,"href="+PassChangeForm.HREF+"?id="+id).text("Try again").end();
+ } else {
+ hgen.incr("a",true,"href="+Home.HREF).text("Home").end();
+ }
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoForm.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoForm.java
new file mode 100644
index 00000000..173b9500
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsInfoForm.java
@@ -0,0 +1,162 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.A;
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TABLE;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Nss;
+import aaf.v2_0.Nss.Ns;
+
+public class NsInfoForm extends Page {
+
+ // Package on purpose
+ static final String HREF = "/gui/onboard";
+ static final String NAME = "Onboarding";
+ static final String fields[] = {"ns","description","mots","owners","admins"};
+
+ public NsInfoForm(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+
+ private final Slot sID = gui.env.slot(NsInfoForm.NAME+'.'+NsInfoForm.fields[0]);
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ // p tags not closing right using .p() - causes issues in IE8 password form - so using leaf for the moment
+ hgen.leaf(HTMLGen.H2).text("Namespace Info").end()
+ .leaf("p").text("Hover over Fields for Tool Tips, or click ")
+ .leaf(A,"href="+gui.env.getProperty(AAF_URL_GUI_ONBOARD,"")).text("Here").end()
+ .text(" for more information")
+ .end()
+ .incr("form","method=post");
+ Mark table = new Mark(TABLE);
+ hgen.incr(table);
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final String incomingID= trans.get(sID, "");
+ final String[] info = new String[fields.length];
+ final Object own_adm[] = new Object[2];
+ for(int i=0;i<info.length;++i) {
+ info[i]="";
+ }
+ if(incomingID.length()>0) {
+ TimeTaken tt = trans.start("AAF Namespace Info",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Nss> fn = client.read("/authz/nss/"+incomingID,gui.getDF(Nss.class));
+ if(fn.get(AAF_GUI.TIMEOUT)) {
+ for(Ns ns : fn.value.getNs()) {
+ info[0]=ns.getName();
+ info[1]=ns.getDescription();
+ for(Ns.Attrib attr: ns.getAttrib()) {
+ switch(attr.getKey()) {
+ case "mots":
+ info[2]=attr.getValue();
+ default:
+ }
+ }
+ own_adm[0]=ns.getResponsible();
+ own_adm[1]=ns.getAdmin();
+ }
+ } else {
+ trans.error().log(fn.body());
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log("Unable to access AAF for NS Info",incomingID);
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+ }
+ hgen.input(fields[0],"Namespace",false,"value="+info[0],"title=AAF Namespace")
+ .input(fields[1],"Description*",true,"value="+info[1],"title=Full Application Name, Tool Name or Group")
+ .input(fields[2],"MOTS ID",false,"value="+info[2],"title=MOTS ID if this is an Application, and has MOTS");
+ Mark endTD = new Mark(),endTR=new Mark();
+ // Owners
+ hgen.incr(endTR,HTMLGen.TR)
+ .incr(endTD,HTMLGen.TD)
+ .leaf("label","for="+fields[3]).text("Responsible Party")
+ .end(endTD)
+ .incr(endTD,HTMLGen.TD)
+ .tagOnly("input","id="+fields[3],"title=Owner of App, must be an Non-Bargained Employee");
+ if(own_adm[0]!=null) {
+ for(String s : (List<String>)own_adm[0]) {
+ hgen.incr("label",true).text(s).end();
+ }
+ }
+ hgen.end(endTR);
+
+ // Admins
+ hgen.incr(endTR,HTMLGen.TR)
+ .incr(endTD,HTMLGen.TD)
+ .leaf("label","for="+fields[4]).text("Administrators")
+ .end(endTD)
+ .incr(endTD,HTMLGen.TD)
+ .tagOnly("input","id="+fields[4],"title=Admins may be employees, contractors or mechIDs");
+ if(own_adm[1]!=null) {
+ for(String s : (List<String>)own_adm[1]) {
+ hgen.incr(HTMLGen.P,true).text(s).end();
+ }
+ }
+ hgen.end(endTR)
+ .end();
+ }
+ });
+ hgen.end();
+ hgen.tagOnly("input", "type=submit", "value=Submit")
+ .end();
+
+ }
+ });
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NssShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NssShow.java
new file mode 100644
index 00000000..02aedc5a
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NssShow.java
@@ -0,0 +1,142 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+
+import aaf.v2_0.Nss;
+import aaf.v2_0.Nss.Ns;
+
+public class NssShow extends Page {
+ public static final String HREF = "/gui/ns";
+
+ public NssShow(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, "MyNamespaces",HREF, NO_FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Namespaces I administer",gui.env.newTransNoAvg(),new Model(true,"Administrator",gui.env),
+ "class=std", "style=display: inline-block; width: 45%; margin: 10px;"),
+ new Table<AAF_GUI,AuthzTrans>("Namespaces I own",gui.env.newTransNoAvg(),new Model(false,"Owner",gui.env),
+ "class=std", "style=display: inline-block; width: 45%; margin: 10px;"));
+ }
+
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private String[] headers;
+ private String privilege = null;
+ public final Slot sNssByUser;
+ private boolean isAdmin;
+
+ public Model(boolean admin, String privilege,AuthzEnv env) {
+ super();
+ headers = new String[] {privilege};
+ this.privilege = privilege;
+ isAdmin = admin;
+ sNssByUser = env.slot("NSS_SHOW_MODEL_DATA");
+ }
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ List<Ns> nss = trans.get(sNssByUser, null);
+ if(nss==null) {
+ TimeTaken tt = trans.start("AAF Nss by User for " + privilege,Env.REMOTE);
+ try {
+ nss = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<List<Ns>>() {
+ @Override
+ public List<Ns> code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ List<Ns> nss = null;
+ Future<Nss> fp = client.read("/authz/nss/either/" + trans.user(),gui.getDF(Nss.class));
+ if(fp.get(AAF_GUI.TIMEOUT)) {
+ TimeTaken tt = trans.start("Load Data for " + privilege, Env.SUB);
+ try {
+ if(fp.value!=null) {
+ nss = fp.value.getNs();
+ Collections.sort(nss, new Comparator<Ns>() {
+ public int compare(Ns ns1, Ns ns2) {
+ return ns1.getName().compareToIgnoreCase(ns2.getName());
+ }
+ });
+ trans.put(sNssByUser,nss);
+ }
+ } finally {
+ tt.done();
+ }
+ }else {
+ gui.writeError(trans, fp, null,0);
+ }
+ return nss;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+ if(nss!=null) {
+ for(Ns n : nss) {
+ if((isAdmin && !n.getAdmin().isEmpty())
+ || (!isAdmin && !n.getResponsible().isEmpty())) {
+ AbsCell[] sa = new AbsCell[] {
+ new RefCell(n.getName(),NsDetail.HREF
+ +"?ns="+n.getName(),false),
+ };
+ rv.add(sa);
+ }
+ }
+ }
+
+ return new Cells(rv,null);
+ }
+ }
+
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeAction.java
new file mode 100644
index 00000000..d0d03a7a
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeAction.java
@@ -0,0 +1,211 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.text.ParseException;
+import java.util.GregorianCalendar;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.cmd.user.Cred;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.org.Organization;
+import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.auth.org.OrganizationFactory;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Chrono;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.CredRequest;
+import aaf.v2_0.Users;
+
+public class PassChangeAction extends Page {
+
+ public PassChangeAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,PassChangeForm.NAME,PassChangeForm.HREF, PassChangeForm.fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sID = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[0]);
+ final Slot sCurrPass = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[1]);
+ final Slot sPassword = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[2]);
+ final Slot sPassword2 = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[3]);
+ final Slot startDate = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[4]);
+ final Slot sNS = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[5]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final String id = trans.get(sID,null);
+ final String currPass = trans.get(sCurrPass,null);
+ final String password = trans.get(sPassword,null);
+ final String password2 = trans.get(sPassword2,null);
+ final String ns = trans.get(sNS, null);
+
+ // Run Validations
+ boolean fail = true;
+
+ if (id==null || id.indexOf('@')<=0) {
+ hgen.p("Data Entry Failure: Please enter a valid ID, including domain.");
+ } else if(password == null || password2 == null) {
+ hgen.p("Data Entry Failure: Both Password Fields need entries.");
+ } else if(!password.equals(password2)) {
+ hgen.p("Data Entry Failure: Passwords do not match.");
+ } else { // everything else is checked by Server
+ final CredRequest cred = new CredRequest();
+ cred.setId(id);
+ cred.setPassword("".equals(currPass)?null:currPass);
+ try {
+ fail = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ boolean fail = true;
+ boolean go = false;
+ try {
+ Organization org = OrganizationFactory.obtain(trans.env(), id);
+ if(org!=null) {
+ go = PassChangeForm.skipCurrent(trans, org.getIdentity(trans, id));
+ }
+ } catch(OrganizationException e) {
+ trans.error().log(e);
+ }
+
+ if(cred.getPassword()==null) {
+ try {
+ if(!go) {
+ go=gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Users> fc = client.read("/authn/creds/id/"+id,gui.getDF(Users.class));
+ if(fc.get(AAFcli.timeout())) {
+ GregorianCalendar now = new GregorianCalendar();
+ for(aaf.v2_0.Users.User u : fc.value.getUser()) {
+ if(u.getType()<10 && u.getExpires().toGregorianCalendar().after(now)) {
+ return false; // an existing, non expired, password type exists
+ }
+ }
+ return true; // no existing, no expired password
+ } else {
+ if(fc.code()==404) { // not found...
+ return true;
+ } else {
+ trans.error().log(gui.aafCon.readableErrMsg(fc));
+ }
+ }
+ return false;
+ }
+ });
+ }
+ if(!go) {
+ hgen.p("Current Password required").br();
+ }
+ } catch (LocatorException e) {
+ trans.error().log(e);
+ }
+
+ } else {
+ TimeTaken tt = trans.start("Check Current Password",Env.REMOTE);
+ try {
+ // Note: Need "Post", because of hiding password in SSL Data
+ Future<CredRequest> fcr = client.create("/authn/validate",gui.getDF(CredRequest.class),cred);
+ fcr.get(5000);
+ if(fcr.code() == 200) {
+ hgen.p("Current Password validated").br();
+ go = true;
+ } else {
+ hgen.p(Cred.ATTEMPT_FAILED_SPECIFICS_WITHELD).br();
+ trans.info().log("Failed Validation",fcr.code(),fcr.body());
+ go = false;
+ }
+ } finally {
+ tt.done();
+ }
+ }
+ if(go) {
+ TimeTaken tt = trans.start("AAF Change Password",Env.REMOTE);
+ try {
+ // Change over Cred to reset mode
+ cred.setPassword(password);
+ String start = trans.get(startDate, null);
+ if(start!=null) {
+ try {
+ cred.setStart(Chrono.timeStamp(Chrono.dateOnlyFmt.parse(start)));
+ } catch (ParseException e) {
+ throw new CadiException(e);
+ }
+ }
+
+ Future<CredRequest> fcr = gui.clientAsUser(trans.getUserPrincipal()).create("/authn/cred",gui.getDF(CredRequest.class),cred);
+ if(fcr.get(AAFcli.timeout())) {
+ // Do Remote Call
+ hgen.p("New Password has been added. The previous one is still valid until Expiration.");
+ fail = false;
+ } else {
+ hgen.p(Cred.ATTEMPT_FAILED_SPECIFICS_WITHELD).br();
+ trans.info().log("Failed Validation",fcr.code(),fcr.body());
+ }
+ } finally {
+ tt.done();
+ }
+ }
+ return fail;
+ }
+
+ });
+ } catch (Exception e) {
+ hgen.p("Unknown Error");
+ e.printStackTrace();
+ }
+
+ }
+ hgen.br();
+ if(fail) {
+ hgen.incr(HTMLGen.A,true,"class=greenbutton","href="+PassChangeForm.HREF+"?id="+id).text("Try again").end();
+ } else {
+ if(ns==null) {
+ hgen.incr(HTMLGen.A,true,"class=greenbutton","href="+Home.HREF).text("Back").end();
+ } else {
+ hgen.incr(HTMLGen.A,true,"class=greenbutton","href="+CredDetail.HREF+"?id="+id+"&ns="+ns).text("Back").end();
+ }
+ }
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeForm.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeForm.java
new file mode 100644
index 00000000..897796d6
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassChangeForm.java
@@ -0,0 +1,205 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TABLE;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.GregorianCalendar;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.org.Organization;
+import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.auth.org.OrganizationFactory;
+import org.onap.aaf.auth.org.Organization.Identity;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Users;
+
+public class PassChangeForm extends Page {
+ // Package on purpose
+ static final String HREF = "/gui/passwd";
+ static final String NAME = "PassChange";
+ static final String fields[] = {"id","current","password","password2","startDate","ns"};
+
+ public PassChangeForm(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,NAME) {
+ private final Slot sID = gui.env.slot(PassChangeForm.NAME+'.'+PassChangeForm.fields[0]);
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+
+ // p tags not closing right using .p() - causes issues in IE8 password form - so using leaf for the moment
+ hgen.incr(HTMLGen.H4,true,"style=margin: 0em 0em .4em 0em")
+ .text("You are <i>adding</i> a New Password in the AAF System.")
+ .end();
+
+ Mark form = new Mark();
+ hgen.incr(form,"form","method=post");
+
+ Mark table = new Mark(TABLE);
+ hgen.incr(table);
+
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String incomingID= trans.get(sID, "");
+ boolean skipCurrent = false;
+ if(incomingID.length()>0) {
+ try {
+ Organization org = OrganizationFactory.obtain(trans.env(), incomingID);
+ if(org==null) {
+ hgen.incr(HTMLGen.H4,"style=color:red;").text("Error: There is no supported company for ").text(incomingID).end();
+ } else {
+ Identity user = org.getIdentity(trans, incomingID);
+ if(user==null) {
+ int at = incomingID.indexOf('@');
+ hgen.incr(HTMLGen.H4,"style=color:red;").text("Error: You are not the sponsor of '").text(at<0?incomingID:incomingID.substring(0,at))
+ .text("' defined at ").text(org.getName()).end();
+ incomingID = "";
+ } else {
+ // Owners/or the IDs themselves are allowed to reset password without previous one
+ skipCurrent=skipCurrent(trans, user);
+
+ if(!skipCurrent) {
+ final String id = incomingID;
+ try {
+ skipCurrent=gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Users> fc = client.read("/authn/creds/id/"+id,gui.getDF(Users.class));
+ if(fc.get(AAFcli.timeout())) {
+ GregorianCalendar now = new GregorianCalendar();
+ for(aaf.v2_0.Users.User u : fc.value.getUser()) {
+ if(u.getType()<10 && u.getType()>=1 && u.getExpires().toGregorianCalendar().after(now)) {
+ return false; // an existing, non expired, password type exists
+ }
+ }
+ return true; // no existing, no expired password
+ } else {
+ if(fc.code()==404) { // not found...
+ return true;
+ } else {
+ trans.error().log(gui.aafCon.readableErrMsg(fc));
+ }
+ }
+ return false;
+ }
+ });
+ } catch (LocatorException | CadiException e) {
+ trans.error().log(e);
+ }
+ }
+ }
+ }
+ } catch (OrganizationException e) {
+ hgen.incr(HTMLGen.H4,"style=color:red;").text("Error: ")
+ .text(e.getMessage()).end();
+ }
+ }
+
+ hgen.input(fields[0],"ID*",true,"value="+incomingID,(incomingID.length()==0?"":"readonly"));
+ if(!skipCurrent) {
+ hgen.input(fields[1],"Current Password*",true,"type=password");
+ }
+ if(skipCurrent) {
+ hgen.input(fields[1],"",false,"type=hidden", "value=").end();
+ }
+
+ hgen.input(fields[2],"New Password*",true, "type=password")
+ .input(fields[3], "Reenter New Password*",true, "type=password")
+ // .input(fields[3],"Start Date",false,"type=date", "value="+
+ // Chrono.dateOnlyFmt.format(new Date(System.currentTimeMillis()))
+ // )
+ .end(table);
+
+ }
+
+ });
+ hgen.tagOnly("input", "type=submit", "value=Submit")
+ .end(form)
+ .br()
+ .p("All AAF Passwords continue to be valid until their listed expiration dates. ",
+ "This allows you to migrate services to this new password until the old ones expire.").br().br()
+ .p("Note: You must be an Admin of the Namespace where the MechID is defined.").br()
+ ;
+
+ Mark div = hgen.divID("passwordRules");
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ try {
+ Organization org = OrganizationFactory.obtain(trans.env(),trans.getUserPrincipal().getName());
+ if(org!=null) {
+ hgen.incr(HTMLGen.H4).text("Password Rules for ").text(org.getName()).end()
+ .incr(HTMLGen.UL);
+ for(String line : org.getPasswordRules()) {
+ hgen.leaf(HTMLGen.LI).text(line).end();
+ }
+ hgen.end();
+ }
+ } catch (OrganizationException e) {
+ hgen.p("No Password Rules can be found for company of ID ",trans.getUserPrincipal().getName()).br();
+ }
+ }
+ });
+ hgen.end(div);
+ }
+ }
+ );
+ }
+
+ // Package on Purpose
+ static boolean skipCurrent(AuthzTrans trans, Identity user) throws OrganizationException {
+ if(user!=null) {
+ // Should this be an abstractable Policy?
+ String tuser = trans.user();
+ if(user.fullID().equals(trans.user())) {
+ return true;
+ } else {
+ Identity manager = user.responsibleTo();
+ if(tuser.equals(user.fullID()) || manager.isFound()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassDeleteAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassDeleteAction.java
new file mode 100644
index 00000000..49daf022
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PassDeleteAction.java
@@ -0,0 +1,88 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.SlotCode;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.CredRequest;
+
+public class PassDeleteAction extends Page {
+ public static final String NAME = "PassDeleteAction";
+ public static final String HREF = "/gui/passdelete";
+ private static enum Params{id,date,ns,type};
+
+ public PassDeleteAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF,Params.values(),
+ new BreadCrumbs(breadcrumbs),
+ new SlotCode<AuthzTrans>(true,gui.env,NAME,Params.values()) {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final CredRequest cr = new CredRequest();
+ cr.setId(get(trans,Params.id, ""));
+ cr.setType(Integer.parseInt(get(trans,Params.type, "0")));
+ cr.setEntry(get(trans,Params.date,"1960-01-01"));
+ try {
+ String err = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<String>() {
+ @Override
+ public String code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<CredRequest> fcr = client.delete("/authn/cred", gui.getDF(CredRequest.class),cr);
+ if(!fcr.get(AAFcli.timeout())) {
+ return gui.aafCon.readableErrMsg(fcr);
+ }
+ return null;
+ }
+ });
+ if(err==null) {
+ hgen.p("Password " + cr.getId() + ", " + cr.getEntry() + " is Deleted");
+ } else {
+ hgen.p(err);
+ }
+ } catch (LocatorException | CadiException e) {
+ throw new APIException(e);
+ }
+ }
+ });
+ }
+ }
+ );
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java
new file mode 100644
index 00000000..e55d803c
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java
@@ -0,0 +1,193 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Approval;
+import aaf.v2_0.Approvals;
+
+public class PendingRequestsShow extends Page {
+ public static final String HREF = "/gui/myrequests";
+ public static final String NAME = "MyRequests";
+ static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id=";
+ private static DateFormat createdDF = new SimpleDateFormat("yyyy-MM-dd");
+
+ public PendingRequestsShow(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME,HREF, NO_FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"expedite") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ hgen
+ .leaf("p", "class=expedite_request").text("These are your submitted Requests that are awaiting Approval. ")
+ .br()
+ .text("To Expedite a Request: ")
+ .leaf("a","href=#expedite_directions","onclick=divVisibility('expedite_directions');")
+ .text("Click Here").end()
+ .divID("expedite_directions", "style=display:none");
+ hgen
+ .incr(HTMLGen.OL)
+ .incr(HTMLGen.LI)
+ .leaf("a","href="+ApprovalForm.HREF+"?user="+trans.user(), "id=userApprove")
+ .text("Copy This Link")
+ .end()
+ .end()
+ .incr(HTMLGen.LI)
+ .text("Send it to the Approver Listed")
+ .end()
+ .end()
+ .text("NOTE: Using this link, the Approver will only see your requests. You only need to send this link once!")
+ .end()
+ .end();
+ }
+ });
+ }
+ },
+ new Table<AAF_GUI,AuthzTrans>("Pending Requests",gui.env.newTransNoAvg(),new Model(), "class=std")
+ );
+
+
+ }
+
+ /**
+ * Implement the Table Content for Requests by User
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String CSP_ATT_COM = "@csp.att.com";
+ final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L;
+ private static final String[] headers = new String[] {"Request Date","Status","Memo","Approver"};
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("AAF Get Approvals by User",Env.REMOTE);
+ try {
+ Future<Approvals> fa = client.read("/authz/approval/user/"+trans.user(),gui.getDF(Approvals.class));
+ if(fa.get(5000)) {
+ tt.done();
+ tt = trans.start("Load Data", Env.SUB);
+ if(fa.value!=null) {
+ List<Approval> approvals = fa.value.getApprovals();
+ Collections.sort(approvals, new Comparator<Approval>() {
+ @Override
+ public int compare(Approval a1, Approval a2) {
+ UUID id1 = UUID.fromString(a1.getId());
+ UUID id2 = UUID.fromString(a2.getId());
+ return id1.timestamp()<=id2.timestamp()?1:-1;
+ }
+ });
+
+ String prevTicket = null;
+ for(Approval a : approvals) {
+ String approver = a.getApprover();
+ String approverShort = approver.substring(0,approver.indexOf('@'));
+
+ AbsCell tsCell = null;
+ String ticket = a.getTicket();
+ if (ticket==null || ticket.equals(prevTicket)) {
+ tsCell = AbsCell.Null;
+ } else {
+ UUID id = UUID.fromString(a.getId());
+ tsCell = new RefCell(createdDF.format((id.timestamp() - NUM_100NS_INTERVALS_SINCE_UUID_EPOCH)/10000),
+ RequestDetail.HREF + "?ticket=" + ticket,false);
+ prevTicket = ticket;
+ }
+
+ AbsCell approverCell = null;
+ if (approver.endsWith(CSP_ATT_COM)) {
+ approverCell = new RefCell(approver, WEBPHONE + approverShort,true);
+ } else {
+ approverCell = new TextCell(approver);
+ }
+ AbsCell[] sa = new AbsCell[] {
+ tsCell,
+ new TextCell(a.getStatus()),
+ new TextCell(a.getMemo()),
+ approverCell
+ };
+ rv.add(sa);
+ }
+ }
+ } else {
+ gui.writeError(trans, fa, null, 0);
+ }
+ } finally {
+ tt.done();
+ }
+
+
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ }
+ return new Cells(rv,null);
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java
new file mode 100644
index 00000000..822d0bf4
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java
@@ -0,0 +1,160 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.auth.validation.Validator;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+
+import aaf.v2_0.Perm;
+import aaf.v2_0.Perms;
+
+/**
+ * Detail Page for Permissions
+ *
+ * @author Jonathan
+ *
+ */
+public class PermDetail extends Page {
+ public static final String HREF = "/gui/permdetail";
+ public static final String NAME = "PermDetail";
+ private static final String BLANK = "";
+
+ public PermDetail(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, new String[] {"type","instance","action"},
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Permission Details",gui.env.newTransNoAvg(),new Model(gui.env),"class=detail")
+ );
+ }
+
+ /**
+ * Implement the table content for Permissions Detail
+ *
+ * @author Jonathan
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private Slot type, instance, action;
+ public Model(AuthzEnv env) {
+ type = env.slot(NAME+".type");
+ instance = env.slot(NAME+".instance");
+ action = env.slot(NAME+".action");
+ }
+
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String pType = trans.get(type, null);
+ final String pInstance = trans.get(instance, null);
+ final String pAction = trans.get(action, null);
+ Validator v = new Validator();
+ v.permType(pType)
+ .permInstance(pInstance)
+ .permAction(pAction);
+
+ if(v.err()) {
+ trans.warn().printf("Error in PermDetail Request: %s", v.errs());
+ return Cells.EMPTY;
+ }
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ rv.add(new AbsCell[]{new TextCell("Type:"),new TextCell(pType)});
+ rv.add(new AbsCell[]{new TextCell("Instance:"),new TextCell(pInstance)});
+ rv.add(new AbsCell[]{new TextCell("Action:"),new TextCell(pAction)});
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("AAF Perm Details",Env.REMOTE);
+ try {
+ Future<Perms> fp= client.read("/authz/perms/"+pType + '/' + pInstance + '/' + pAction,gui.getDF(Perms.class));
+
+ if(fp.get(AAF_GUI.TIMEOUT)) {
+ tt.done();
+ tt = trans.start("Load Data", Env.SUB);
+ List<Perm> ps = fp.value.getPerm();
+ if(!ps.isEmpty()) {
+ Perm perm = fp.value.getPerm().get(0);
+ String desc = (perm.getDescription()!=null?perm.getDescription():BLANK);
+ rv.add(new AbsCell[]{new TextCell("Description:"),new TextCell(desc)});
+ boolean first=true;
+ for(String r : perm.getRoles()) {
+ if(first){
+ first=false;
+ rv.add(new AbsCell[] {
+ new TextCell("Associated Roles:"),
+ new TextCell(r)
+ });
+ } else {
+ rv.add(new AbsCell[] {
+ AbsCell.Null,
+ new TextCell(r)
+ });
+ }
+ }
+ }
+ String historyLink = PermHistory.HREF
+ + "?type=" + pType + "&instance=" + pInstance + "&action=" + pAction;
+
+ rv.add(new AbsCell[] {new RefCell("See History",historyLink,false)});
+ } else {
+ rv.add(new AbsCell[] {new TextCell(
+ fp.code()==HttpStatus.NOT_FOUND_404?
+ "*** Implicit Permission ***":
+ "*** Data Unavailable ***"
+ )});
+ }
+ } finally {
+ tt.done();
+ }
+
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return new Cells(rv,null);
+ }
+ }
+}
+ \ No newline at end of file
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantAction.java
new file mode 100644
index 00000000..dd854660
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantAction.java
@@ -0,0 +1,135 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Pkey;
+import aaf.v2_0.RolePermRequest;
+
+public class PermGrantAction extends Page {
+
+
+ public PermGrantAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,PermGrantForm.NAME, PermGrantForm.HREF, PermGrantForm.fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sType = gui.env.slot(PermGrantForm.NAME+'.'+PermGrantForm.fields[0]);
+ final Slot sInstance = gui.env.slot(PermGrantForm.NAME+'.'+PermGrantForm.fields[1]);
+ final Slot sAction = gui.env.slot(PermGrantForm.NAME+'.'+PermGrantForm.fields[2]);
+ final Slot sRole = gui.env.slot(PermGrantForm.NAME+'.'+PermGrantForm.fields[3]);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+
+ String type = trans.get(sType,null);
+ String instance = trans.get(sInstance,null);
+ String action = trans.get(sAction,null);
+ String role = trans.get(sRole,null);
+
+ String lastPage = PermGrantForm.HREF
+ + "?type=" + type + "&instance=" + instance + "&action=" + action;
+
+ // Run Validations
+ boolean fail = true;
+
+ TimeTaken tt = trans.start("AAF Grant Permission to Role",Env.REMOTE);
+ try {
+
+ final RolePermRequest grantReq = new RolePermRequest();
+ Pkey pkey = new Pkey();
+ pkey.setType(type);
+ pkey.setInstance(instance);
+ pkey.setAction(action);
+ grantReq.setPerm(pkey);
+ grantReq.setRole(role);
+
+ fail = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ boolean fail = true;
+ Future<RolePermRequest> fgrant = client.create(
+ "/authz/role/perm",
+ gui.getDF(RolePermRequest.class),
+ grantReq
+ );
+
+ if(fgrant.get(5000)) {
+ hgen.p("Permission has been granted to role.");
+ fail = false;
+ } else {
+ if (202==fgrant.code()) {
+ hgen.p("Permission Grant Request sent, but must be Approved before actualizing");
+ fail = false;
+ } else {
+ gui.writeError(trans, fgrant, hgen, 0);
+ }
+ }
+ return fail;
+ }
+ });
+ } catch (Exception e) {
+ hgen.p("Unknown Error");
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+
+ hgen.br();
+ hgen.incr("a",true,"href="+lastPage);
+ if (fail) {
+ hgen.text("Try again");
+ } else {
+ hgen.text("Grant this Permission to Another Role");
+ }
+ hgen.end();
+ hgen.js()
+ .text("alterLink('permgrant', '"+lastPage + "');")
+ .done();
+
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantForm.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantForm.java
new file mode 100644
index 00000000..1c5bc4c1
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermGrantForm.java
@@ -0,0 +1,157 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.TABLE;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Role;
+import aaf.v2_0.Roles;
+
+public class PermGrantForm extends Page {
+ static final String HREF = "/gui/permgrant";
+ static final String NAME = "Permission Grant";
+ static final String fields[] = {"type","instance","action","role"};
+
+ public PermGrantForm(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final Slot type = gui.env.slot(NAME+".type");
+ final Slot instance = gui.env.slot(NAME+".instance");
+ final Slot action = gui.env.slot(NAME+".action");
+ final Slot role = gui.env.slot(NAME+".role");
+ // p tags not closing right using .p() - causes issues in IE8 password form - so using leaf for the moment
+ hgen.leaf("p").text("Choose a role to grant to this permission").end()
+ .incr("form","method=post");
+ Mark table = new Mark(TABLE);
+ hgen.incr(table);
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+
+ Mark copyRoleJS = new Mark();
+ hgen.js(copyRoleJS);
+ hgen.text("function copyRole(role) {");
+ hgen.text("var txtRole = document.querySelector(\"#role\");");
+// hgen.text("if (role==;");
+ hgen.text("txtRole.value=role;");
+ hgen.text("}");
+ hgen.end(copyRoleJS);
+
+ String typeValue = trans.get(type, "");
+ String instanceValue = trans.get(instance, "");
+ String actionValue = trans.get(action, "");
+ String roleValue = trans.get(role,null);
+ List<String> myRoles = getMyRoles(gui, trans);
+ hgen
+ .input(fields[0],"Perm Type",true,"value="+typeValue,"disabled")
+ .input(fields[1],"Perm Instance",true,"value="+instanceValue,"disabled")
+ .input(fields[2],"Perm Action",true,"value="+actionValue,"disabled");
+
+ // select & options are not an input type, so we must create table row & cell tags
+ Mark selectRow = new Mark();
+ hgen
+ .incr(selectRow, "tr")
+ .incr("td")
+ .incr("label", "for=myroles", "required").text("My Roles").end()
+ .end()
+ .incr("td")
+ .incr("select", "name=myroles", "id=myroles", "onchange=copyRole(this.value)")
+ .incr("option", "value=").text("Select one of my roles").end();
+ for (String role : myRoles) {
+ hgen.incr("option", "value="+role).text(role).end();
+ }
+ hgen
+ .incr("option", "value=").text("Other").end()
+ .end(selectRow);
+ if(roleValue==null) {
+ hgen.input(fields[3],"Role", true, "placeholder=or type a role here");
+ } else {
+ hgen.input(fields[3],"Role",true, "value="+roleValue);
+ }
+ hgen.end();
+ }
+ });
+ hgen.end();
+ hgen.tagOnly("input", "type=submit", "value=Submit")
+ .end();
+
+ }
+ });
+ }
+
+ private static List<String> getMyRoles(final AAF_GUI gui, final AuthzTrans trans) {
+ final List<String> myRoles = new ArrayList<String>();
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("AAF get my roles",Env.REMOTE);
+ try {
+ Future<Roles> fr = client.read("/authz/roles/user/"+trans.user(),gui.getDF(Roles.class));
+ if(fr.get(5000)) {
+ tt.done();
+ tt = trans.start("Load Data", Env.SUB);
+ if (fr.value != null) for (Role r : fr.value.getRole()) {
+ myRoles.add(r.getName());
+ }
+ } else {
+ gui.writeError(trans, fr, null, 0);
+ }
+ } finally {
+ tt.done();
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return myRoles;
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java
new file mode 100644
index 00000000..45f8b22e
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java
@@ -0,0 +1,243 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.History;
+import aaf.v2_0.History.Item;
+
+
+public class PermHistory extends Page {
+ static final String NAME="PermHistory";
+ static final String HREF = "/gui/permHistory";
+ static final String FIELDS[] = {"type","instance","action","dates"};
+ static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id=";
+ static enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,
+ AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
+
+ public PermHistory(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("History", gui.env.newTransNoAvg(),new Model(gui.env),"class=std"),
+ new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final Slot sType = gui.env.slot(NAME+".type");
+ final Slot sInstance = gui.env.slot(NAME+".instance");
+ final Slot sAction = gui.env.slot(NAME+".action");
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String type = trans.get(sType, null);
+ String instance = trans.get(sInstance,null);
+ String action = trans.get(sAction,null);
+
+ // Use Javascript to make the table title more descriptive
+ hgen.js()
+ .text("var caption = document.querySelector(\".title\");")
+ .text("caption.innerHTML='History for Permission [ " + type + " ]';")
+ .done();
+
+ // Use Javascript to change Link Target to our last visited Detail page
+ String lastPage = PermDetail.HREF + "?type=" + type
+ + "&instance=" + instance
+ + "&action=" + action;
+ hgen.js()
+ .text("alterLink('permdetail', '"+lastPage + "');")
+ .done();
+
+ hgen.br();
+ hgen.leaf("a", "href=#advanced_search", "onclick=divVisibility('advanced_search');").text("Advanced Search").end()
+ .divID("advanced_search", "style=display:none");
+ hgen.incr("table");
+
+ addDateRow(hgen,"Start Date");
+ addDateRow(hgen,"End Date");
+ hgen.incr("tr").incr("td");
+ hgen.tagOnly("input", "type=button","value=Get History",
+ "onclick=datesURL('"+HREF+"?type=" + type
+ + "&instance=" + instance
+ + "&action=" + action+"');");
+ hgen.end().end();
+ hgen.end();
+ hgen.end();
+ }
+ });
+ }
+ }
+
+ );
+
+ }
+
+ private static void addDateRow(HTMLGen hgen, String s) {
+ hgen
+ .incr("tr")
+ .incr("td")
+ .incr("label", "for=month", "required").text(s+"*").end()
+ .end()
+ .incr("td")
+ .incr("select", "name=month"+s.substring(0, s.indexOf(' ')), "id=month"+s.substring(0, s.indexOf(' ')), "required")
+ .incr("option", "value=").text("Month").end();
+ for (Month m : Month.values()) {
+ if (Calendar.getInstance().get(Calendar.MONTH) == m.ordinal()) {
+ hgen.incr("option", "selected", "value="+(m.ordinal()+1)).text(m.name()).end();
+ } else {
+ hgen.incr("option", "value="+(m.ordinal()+1)).text(m.name()).end();
+ }
+ }
+ hgen.end()
+ .end()
+ .incr("td")
+ .tagOnly("input","type=number","id=year"+s.substring(0, s.indexOf(' ')),"required",
+ "value="+Calendar.getInstance().get(Calendar.YEAR), "min=1900",
+ "max="+Calendar.getInstance().get(Calendar.YEAR),
+ "placeholder=Year").end()
+ .end();
+ }
+
+ /**
+ * Implement the Table Content for History
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String CSP_ATT_COM = "@csp.att.com";
+ private static final String[] headers = new String[] {"Date","User","Memo"};
+ private Slot sType;
+ private Slot sDates;
+
+ public Model(AuthzEnv env) {
+ sType = env.slot(NAME+".type");
+ sDates = env.slot(NAME+".dates");
+ }
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String oName = trans.get(sType,null);
+ final String oDates = trans.get(sDates,null);
+
+ if(oName==null) {
+ return Cells.EMPTY;
+ }
+
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ String msg = null;
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("AAF Get History for Permission ["+oName+"]",Env.REMOTE);
+ try {
+ if (oDates != null) {
+ client.setQueryParams("yyyymm="+oDates);
+ }
+ Future<History> fh = client.read(
+ "/authz/hist/perm/"+oName,
+ gui.getDF(History.class)
+ );
+
+
+ if (fh.get(AAF_GUI.TIMEOUT)) {
+ tt.done();
+ tt = trans.start("Load History Data", Env.SUB);
+ List<Item> histItems = fh.value.getItem();
+
+ java.util.Collections.sort(histItems, new Comparator<Item>() {
+ @Override
+ public int compare(Item o1, Item o2) {
+ return o2.getTimestamp().compare(o1.getTimestamp());
+ }
+ });
+
+ for (Item i : histItems) {
+ String user = i.getUser();
+ AbsCell userCell = (user.endsWith(CSP_ATT_COM)?
+ new RefCell(user,WEBPHONE + user.substring(0,user.indexOf('@')),true):new TextCell(user));
+
+ rv.add(new AbsCell[] {
+ new TextCell(i.getTimestamp().toGregorianCalendar().getTime().toString()),
+ userCell,
+ new TextCell(i.getMemo())
+ });
+ }
+
+ } else {
+ if (fh.code()==403) {
+ rv.add(new AbsCell[] {new TextCell("You may not view History of Permission [" + oName + "]", "colspan = 3", "class=center")});
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***", "colspan = 3", "class=center")});
+ }
+ }
+ } finally {
+ tt.done();
+ }
+
+ return null;
+ }
+ });
+
+ } catch (Exception e) {
+ trans.error().log(e);
+ }
+ return new Cells(rv,msg);
+ }
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermsShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermsShow.java
new file mode 100644
index 00000000..5f5c2874
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermsShow.java
@@ -0,0 +1,121 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+
+import aaf.v2_0.Perm;
+import aaf.v2_0.Perms;
+
+/**
+ * Page content for My Permissions
+ *
+ * @author Jonathan
+ *
+ */
+public class PermsShow extends Page {
+ public static final String HREF = "/gui/myperms";
+
+ public PermsShow(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, "MyPerms",HREF, NO_FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Permissions",gui.env.newTransNoAvg(),new Model(), "class=std"));
+ }
+
+ /**
+ * Implement the Table Content for Permissions by User
+ *
+ * @author Jonathan
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String[] headers = new String[] {"Type","Instance","Action"};
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ TimeTaken tt = trans.start("AAF Perms by User",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Perms> fp = client.read("/authz/perms/user/"+trans.user(), gui.getDF(Perms.class));
+ if(fp.get(5000)) {
+ TimeTaken ttld = trans.start("Load Data", Env.SUB);
+ try {
+ if(fp.value!=null) {
+ for(Perm p : fp.value.getPerm()) {
+ AbsCell[] sa = new AbsCell[] {
+ new RefCell(p.getType(),PermDetail.HREF
+ +"?type="+p.getType()
+ +"&amp;instance="+p.getInstance()
+ +"&amp;action="+p.getAction(),
+ false),
+ new TextCell(p.getInstance()),
+ new TextCell(p.getAction())
+ };
+ rv.add(sa);
+ }
+ } else {
+ gui.writeError(trans, fp, null,0);
+ }
+ } finally {
+ ttld.done();
+ }
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,null);
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RequestDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RequestDetail.java
new file mode 100644
index 00000000..852bbd44
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RequestDetail.java
@@ -0,0 +1,190 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.UUID;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+
+import aaf.v2_0.Approval;
+import aaf.v2_0.Approvals;
+
+public class RequestDetail extends Page {
+ public static final String HREF = "/gui/requestdetail";
+ public static final String NAME = "RequestDetail";
+ private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ public static final String[] FIELDS = {"ticket"};
+
+ public RequestDetail(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Request Details",gui.env.newTransNoAvg(),new Model(gui.env),"class=detail")
+ );
+ }
+
+ /**
+ * Implement the table content for Request Detail
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id=";
+ private static final String CSP_ATT_COM = "@csp.att.com";
+ final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L;
+ private Slot sTicket;
+ public Model(AuthzEnv env) {
+ sTicket = env.slot(NAME+".ticket");
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ Cells rv=Cells.EMPTY;
+ final String ticket = trans.get(sTicket, null);
+ if(ticket!=null) {
+ try {
+ rv = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Cells>() {
+ @Override
+ public Cells code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("AAF Approval Details",Env.REMOTE);
+ ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ try {
+ Future<Approvals> fa = client.read(
+ "/authz/approval/ticket/"+ticket,
+ gui.getDF(Approvals.class)
+ );
+
+ if(fa.get(AAF_GUI.TIMEOUT)) {
+ if (!trans.user().equals(fa.value.getApprovals().get(0).getUser())) {
+ return Cells.EMPTY;
+ }
+ tt.done();
+ tt = trans.start("Load Data", Env.SUB);
+ boolean first = true;
+ for ( Approval approval : fa.value.getApprovals()) {
+ AbsCell[] approverLine = new AbsCell[4];
+ // only print common elements once
+ if (first) {
+ DateFormat createdDF = new SimpleDateFormat(DATE_TIME_FORMAT);
+ UUID id = UUID.fromString(approval.getId());
+
+ rv.add(new AbsCell[]{new TextCell("Ticket ID:"),new TextCell(approval.getTicket(),"colspan=3")});
+ rv.add(new AbsCell[]{new TextCell("Memo:"),new TextCell(approval.getMemo(),"colspan=3")});
+ rv.add(new AbsCell[]{new TextCell("Requested On:"),
+ new TextCell(createdDF.format((id.timestamp() - NUM_100NS_INTERVALS_SINCE_UUID_EPOCH)/10000),"colspan=3")
+ });
+ rv.add(new AbsCell[]{new TextCell("Operation:"),new TextCell(decodeOp(approval.getOperation()),"colspan=3")});
+ String user = approval.getUser();
+ if (user.endsWith(CSP_ATT_COM)) {
+ rv.add(new AbsCell[]{new TextCell("User:"),
+ new RefCell(user,WEBPHONE + user.substring(0, user.indexOf("@")),true,"colspan=3")});
+ } else {
+ rv.add(new AbsCell[]{new TextCell("User:"),new TextCell(user,"colspan=3")});
+ }
+
+ // headers for listing each approver
+ rv.add(new AbsCell[]{new TextCell(" ","colspan=4","class=blank_line")});
+ rv.add(new AbsCell[]{AbsCell.Null,
+ new TextCell("Approver","class=bold"),
+ new TextCell("Type","class=bold"),
+ new TextCell("Status","class=bold")});
+ approverLine[0] = new TextCell("Approvals:");
+
+ first = false;
+ } else {
+ approverLine[0] = AbsCell.Null;
+ }
+
+ String approver = approval.getApprover();
+ String approverShort = approver.substring(0,approver.indexOf('@'));
+
+ if (approver.endsWith(CSP_ATT_COM)) {
+ approverLine[1] = new RefCell(approver, WEBPHONE + approverShort,true);
+ } else {
+ approverLine[1] = new TextCell(approval.getApprover());
+ }
+
+ String type = approval.getType();
+ if ("owner".equalsIgnoreCase(type)) {
+ type = "resource owner";
+ }
+
+ approverLine[2] = new TextCell(type);
+ approverLine[3] = new TextCell(approval.getStatus());
+ rv.add(approverLine);
+
+ }
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***")});
+ }
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,null);
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ }
+ }
+ return rv;
+ }
+
+ private String decodeOp(String operation) {
+ if ("C".equalsIgnoreCase(operation)) {
+ return "Create";
+ } else if ("D".equalsIgnoreCase(operation)) {
+ return "Delete";
+ } else if ("U".equalsIgnoreCase(operation)) {
+ return "Update";
+ } else if ("G".equalsIgnoreCase(operation)) {
+ return "Grant";
+ } else if ("UG".equalsIgnoreCase(operation)) {
+ return "Un-Grant";
+ }
+ return operation;
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java
new file mode 100644
index 00000000..37526b86
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java
@@ -0,0 +1,295 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.CheckBoxCell;
+import org.onap.aaf.auth.gui.table.CheckBoxCell.ALIGN;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.auth.gui.table.TextInputCell;
+import org.onap.aaf.auth.validation.Validator;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.aaf.AAFPermission;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Chrono;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Pkey;
+import aaf.v2_0.Role;
+import aaf.v2_0.Roles;
+import aaf.v2_0.UserRole;
+import aaf.v2_0.UserRoles;
+
+/**
+ * Detail Page for Permissions
+ *
+ * @author Jonathan
+ *
+ */
+public class RoleDetail extends Page {
+ public static final String HREF = "/gui/roledetail";
+ public static final String NAME = "RoleDetail";
+ private static final String BLANK = "";
+
+ public RoleDetail(final AAF_GUI gui, Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, NAME, HREF, new String[] {"role","ns"},
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Role Details",gui.env.newTransNoAvg(),
+ new Model(gui.env),"class=detail")
+ );
+ }
+
+ /**
+ * Implement the table content for Permissions Detail
+ *
+ * @author Jonathan
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private Slot sRoleName,sRole,sUserRole,sMayWrite,sMayApprove,sMark,sNS;
+ public Model(AuthzEnv env) {
+ sRoleName = env.slot(NAME+".role");
+ sRole = env.slot(NAME+".data.role");
+ sUserRole = env.slot(NAME+".data.userrole");
+ sMayWrite = env.slot(NAME+"mayWrite");
+ sMayApprove = env.slot(NAME+"mayApprove");
+ sMark = env.slot(NAME+"mark");
+ sNS = env.slot(NAME+".ns");
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aaf.auth.gui.table.TableData#prefix(org.onap.aaf.misc.xgen.html.State, com.att.inno.env.Trans, org.onap.aaf.misc.xgen.Cache, org.onap.aaf.misc.xgen.html.HTMLGen)
+ */
+ @Override
+ public void prefix(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ final String pRole = trans.get(sRoleName, null);
+ Validator v = new Validator();
+ v.role(pRole);
+ if(v.err()) {
+ trans.warn().printf("Error in PermDetail Request: %s", v.errs());
+ return;
+ }
+
+
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ TimeTaken tt = trans.start("AAF Role Details",Env.REMOTE);
+ try {
+ Future<Roles> fr = client.read("/authz/roles/"+pRole+"?ns",gui.getDF(Roles.class));
+ Future<UserRoles> fur = client.read("/authz/userRoles/role/"+pRole,gui.getDF(UserRoles.class));
+ if(fr.get(AAF_GUI.TIMEOUT)) {
+ Role role = fr.value.getRole().get(0);
+ trans.put(sRole, role);
+ Boolean mayWrite = trans.fish(new AAFPermission(role.getNs()+".access",":role:"+role.getName(),"write"));
+ trans.put(sMayWrite,mayWrite);
+ Boolean mayApprove = trans.fish(new AAFPermission(role.getNs()+".access",":role:"+role.getName(),"approve"));
+ trans.put(sMayApprove, mayApprove);
+
+ if(mayWrite || mayApprove) {
+ Mark js = new Mark();
+ Mark fn = new Mark();
+ hgen.js(js)
+ .function(fn,"touchedDesc")
+ .li("d=document.getElementById('descText');",
+ "if (d.orig == undefined ) {",
+ " d.orig = d.value;",
+ " d.addEventListener('keyup',changedDesc);",
+ " d.removeEventListener('keypress',touchedDesc);",
+ "}").end(fn)
+ .function(fn,"changedDesc")
+ .li(
+ "dcb=document.getElementById('descCB');",
+ "d=document.getElementById('descText');",
+ "dcb.checked= (d.orig != d.value)"
+ ).end(fn)
+ .end(js);
+
+ Mark mark = new Mark();
+ hgen.incr(mark,"form","method=post");
+ trans.put(sMark, mark);
+ }
+ } else {
+ trans.error().printf("Error calling AAF for Roles in GUI, Role Detail %d: %s",fr.code(),fr.body());
+ return false;
+ }
+
+ if(fur.get(AAF_GUI.TIMEOUT)) {
+ trans.put(sUserRole, fur.value.getUserRole());
+ } else {
+ trans.error().printf("Error calling AAF for UserRoles in GUI, Role Detail %d: %s",fr.code(),fr.body());
+ return false;
+ }
+
+ return true;
+ } finally {
+ tt.done();
+ }
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ }
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String pRole = trans.get(sRoleName, null);
+ final Role role = trans.get(sRole,null);
+ ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+
+ if(role!=null) {
+ boolean mayWrite = trans.get(sMayWrite, false);
+ boolean mayApprove = trans.get(sMayApprove, false);
+
+ String desc = (role.getDescription()!=null?role.getDescription():BLANK);
+ rv.add(new AbsCell[]{
+ new TextCell("Role:","width=45%"),
+ new TextCell(pRole)});
+ if(mayWrite) {
+ rv.add(new AbsCell[]{
+ new TextCell("Description:","width=45%"),
+ new TextInputCell("description","textInput",desc,"id=descText","onkeypress=touchedDesc()"),
+ new CheckBoxCell("desc",ALIGN.left, "changed","id=descCB", "style=visibility: hidden"),
+ });
+ rv.add(AbsCell.HLINE);
+ rv.add(new AbsCell[] {
+ new TextCell("Associated Permissions:","width=25%"),
+ new TextCell("UnGrant","width=10%"),
+ });
+ } else {
+ rv.add(new AbsCell[]{
+ new TextCell("Description:","width=45%"),
+ new TextCell(desc)});
+ }
+ boolean protectedRole = role.getName().endsWith(".owner") ||
+ role.getName().endsWith(".admin");
+ boolean first = true;
+ for(Pkey r : role.getPerms()) {
+ String key=r.getType() + '|' + r.getInstance() + '|' + r.getAction();
+ if(mayWrite) {
+ rv.add(new AbsCell[] {
+ AbsCell.Null,
+ protectedRole && r.getType().endsWith(".access")
+ ?new TextCell("protected","class=protected") // Do not allow ungranting of basic NS perms
+ :new CheckBoxCell("perm.ungrant",key),
+ new TextCell("","width=10%"),
+ new TextCell(key)
+ });
+ } else {
+ if(first) {
+ rv.add(new AbsCell[] {
+ new TextCell("Associated Permissions:","width=45%"),
+ new TextCell(key)
+ });
+ first=false;
+ } else {
+ rv.add(new AbsCell[] {
+ AbsCell.Null,
+ new TextCell(key)
+ });
+ }
+ }
+ }
+
+ if(mayApprove) {
+ rv.add(AbsCell.HLINE);
+
+ //
+ rv.add(new AbsCell[] {
+ new TextCell("Users in Role:","width=25%"),
+ new TextCell("Delete","width=10%"),
+ new TextCell("Extend","width=10%")
+ });
+
+ List<UserRole> userroles = trans.get(sUserRole,null);
+ if(userroles!=null) {
+ for(UserRole ur : userroles) {
+ String tag = "userrole";
+
+ rv.add(new AbsCell[] {
+ AbsCell.Null,
+ new CheckBoxCell(tag+".delete", ur.getUser()),
+ new CheckBoxCell(tag+".extend", ur.getUser()),
+ new TextCell(ur.getUser()),
+ new TextCell(Chrono.dateOnlyStamp(ur.getExpires())
+ )});
+ }
+ }
+ }
+
+ // History
+ rv.add(new AbsCell[] {
+ new RefCell("See History",RoleHistory.HREF + "?role=" + pRole,false)
+ });
+ } else {
+ rv.add(new AbsCell[]{
+ new TextCell("Role:"),
+ new TextCell(pRole)});
+
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***")});
+ }
+ return new Cells(rv, null);
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aaf.auth.gui.table.TableData#postfix(org.onap.aaf.misc.xgen.html.State, com.att.inno.env.Trans, org.onap.aaf.misc.xgen.Cache, org.onap.aaf.misc.xgen.html.HTMLGen)
+ */
+ @Override
+ public void postfix(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ final Mark mark = trans.get(sMark, null);
+ if(mark!=null) {
+ hgen.tagOnly("input", "type=submit", "value=Submit");
+ final String pNS = trans.get(sNS, null);
+ if(pNS!=null && pNS.length()>0) {
+ hgen.leaf(mark,HTMLGen.A,"href="+NsDetail.HREF+"?ns="+pNS,"class=greenbutton").text("Back").end(mark);
+ }
+ hgen.end(mark);
+ }
+
+ }
+ }
+}
+ \ No newline at end of file
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetailAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetailAction.java
new file mode 100644
index 00000000..f2d2c01f
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetailAction.java
@@ -0,0 +1,188 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.util.Split;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.Pkey;
+import aaf.v2_0.RolePermRequest;
+import aaf.v2_0.RoleRequest;
+
+public class RoleDetailAction extends Page {
+ public RoleDetailAction(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,RoleDetail.NAME, RoleDetail.HREF, TableData.headers,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true,"content") {
+ final Slot sReq = gui.env.slot(AAF_GUI.HTTP_SERVLET_REQUEST);
+
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans,final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final HttpServletRequest req = trans.get(sReq, null);
+ final String role = getSingleParam(req,"role");
+ if(role==null) {
+ hgen.text("Parameter 'role' is required").end();
+ } else {
+ // Run Validations
+// boolean fail;
+ try {
+ /*fail =*/ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Boolean>() {
+ @Override
+ public Boolean code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ List<TypedFuture> ltf = new ArrayList<TypedFuture>();
+ String text;
+ Map<String, String[]> pm = (Map<String, String[]>)req.getParameterMap();
+ for(final Entry<String, String[]> es : pm.entrySet()) {
+ for(final String v : es.getValue()) {
+ TimeTaken tt = null;
+ try {
+ switch(es.getKey()) {
+ case "desc": // Check box set
+ String desc = getSingleParam(req, "description");
+ if(desc!=null) {
+ text = "Setting Description on " + role + " to " + desc;
+ tt = trans.start(text, Env.REMOTE);
+ RoleRequest rr = new RoleRequest();
+ rr.setName(role);
+ rr.setDescription(desc);
+ ltf.add(new TypedFuture(ActionType.desc, text,
+ client.update("/authz/role",
+ gui.getDF(RoleRequest.class),rr
+ )));
+ }
+ break;
+ case "perm.ungrant":
+ text = "Ungranting Permission '" + v + "' from '" + role + '\'';
+ tt = trans.start(text, Env.REMOTE);
+ String[] pf = Split.splitTrim('|', v);
+ if(pf.length==3) {
+ Pkey perm = new Pkey();
+ perm.setType(pf[0]);
+ perm.setInstance(pf[1]);
+ perm.setAction(pf[2]);
+ RolePermRequest rpr = new RolePermRequest();
+ rpr.setPerm(perm);
+ rpr.setRole(role);
+ ltf.add(new TypedFuture(ActionType.ungrant,text,
+ client.delete("/authz/role/" + role + "/perm",
+ gui.getDF(RolePermRequest.class),rpr
+ )));
+ } else {
+ hgen.p(v + " is not a valid Perm for ungranting");
+ }
+ break;
+ case "userrole.extend":
+ text = "Extending " + v + " in " + role;
+ tt = trans.start(text, Env.REMOTE);
+ ltf.add(new TypedFuture(ActionType.extendUR,text,
+ client.update("/authz/userRole/extend/" + v + '/' + role)));
+ break;
+ case "userrole.delete":
+ text = "Deleting " + v + " from " + role;
+ tt = trans.start(text, Env.REMOTE);
+ ltf.add(new TypedFuture(ActionType.deleteUR,text,
+ client.delete("/authz/userRole/" + v + '/' + role, Void.class)));
+ break;
+
+ default:
+// System.out.println(es.getKey() + "=" + v);
+ }
+ } finally {
+ if(tt!=null) {
+ tt.done();
+ tt=null;
+ }
+ }
+ }
+ }
+
+ if(ltf.isEmpty()) {
+ hgen.p("No Changes");
+ } else {
+ for(TypedFuture tf : ltf) {
+ if(tf.future.get(5000)) {
+ hgen.p("<font color=\"green\"><i>Success</i>:</font> " + tf.text);
+ } else {
+ // Note: if handling of special Error codes is required, use
+ // switch(tf.type) {
+ // }
+ hgen.p(tf.text);
+ gui.writeError(trans, tf.future, hgen,4);
+ }
+ }
+ }
+ return true;
+ }
+ });
+ } catch (Exception e) {
+ hgen.p("Unknown Error");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ });
+ }
+ });
+ }
+
+ enum ActionType {desc, ungrant, deleteUR, extendUR};
+ private static class TypedFuture {
+// public final ActionType type;
+ public final Future<?> future;
+ public final String text;
+
+ public TypedFuture(ActionType type, String text, Future<?> future) {
+// this.type = type;
+ this.future = future;
+ this.text = text;
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java
new file mode 100644
index 00000000..e80a5917
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java
@@ -0,0 +1,228 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.List;
+
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+import aaf.v2_0.History;
+import aaf.v2_0.History.Item;
+
+
+public class RoleHistory extends Page {
+ static final String NAME="RoleHistory";
+ static final String HREF = "/gui/roleHistory";
+ static final String FIELDS[] = {"role","dates"};
+ static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id=";
+ static enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,
+ AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
+
+ public RoleHistory(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME,HREF, FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("History", gui.env.newTransNoAvg(),new Model(gui.env),"class=std"),
+ new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final Slot role = gui.env.slot(NAME+".role");
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ String obRole = trans.get(role, null);
+
+ // Use Javascript to make the table title more descriptive
+ hgen.js()
+ .text("var caption = document.querySelector(\".title\");")
+ .text("caption.innerHTML='History for Role [ " + obRole + " ]';")
+ .done();
+
+ // Use Javascript to change Link Target to our last visited Detail page
+ String lastPage = RoleDetail.HREF + "?role=" + obRole;
+ hgen.js()
+ .text("alterLink('roledetail', '"+lastPage + "');")
+ .done();
+
+ hgen.br();
+ hgen.leaf("a", "href=#advanced_search","onclick=divVisibility('advanced_search');").text("Advanced Search").end()
+ .divID("advanced_search", "style=display:none");
+ hgen.incr("table");
+
+ addDateRow(hgen,"Start Date");
+ addDateRow(hgen,"End Date");
+ hgen.incr("tr").incr("td");
+ hgen.tagOnly("input", "type=button","value=Get History",
+ "onclick=datesURL('"+HREF+"?role=" + obRole+"');");
+ hgen.end().end();
+ hgen.end();
+ hgen.end();
+ }
+ });
+ }
+ }
+
+ );
+
+ }
+
+ private static void addDateRow(HTMLGen hgen, String s) {
+ hgen
+ .incr("tr")
+ .incr("td")
+ .incr("label", "for=month", "required").text(s+"*").end()
+ .end()
+ .incr("td")
+ .incr("select", "name=month"+s.substring(0, s.indexOf(' ')), "id=month"+s.substring(0, s.indexOf(' ')), "required")
+ .incr("option", "value=").text("Month").end();
+ for (Month m : Month.values()) {
+ if (Calendar.getInstance().get(Calendar.MONTH) == m.ordinal()) {
+ hgen.incr("option", "selected", "value="+(m.ordinal()+1)).text(m.name()).end();
+ } else {
+ hgen.incr("option", "value="+(m.ordinal()+1)).text(m.name()).end();
+ }
+ }
+ hgen.end()
+ .end()
+ .incr("td")
+ .tagOnly("input","type=number","id=year"+s.substring(0, s.indexOf(' ')),"required",
+ "value="+Calendar.getInstance().get(Calendar.YEAR), "min=1900",
+ "max="+Calendar.getInstance().get(Calendar.YEAR),
+ "placeholder=Year").end()
+ .end();
+ }
+
+
+ /**
+ * Implement the Table Content for History
+ *
+ * @author Jeremiah
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String CSP_ATT_COM = "@csp.att.com";
+ private static final String[] headers = new String[] {"Date","User","Memo"};
+ private Slot role;
+ private Slot dates;
+
+ public Model(AuthzEnv env) {
+ role = env.slot(NAME+".role");
+ dates = env.slot(NAME+".dates");
+ }
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ final String oName = trans.get(role,null);
+ final String oDates = trans.get(dates,null);
+
+ Cells rv = Cells.EMPTY;
+ if(oName!=null) {
+
+ try {
+ rv = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Cells>() {
+ @Override
+ public Cells code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ TimeTaken tt = trans.start("AAF Get History for Namespace ["+oName+"]",Env.REMOTE);
+ String msg = null;
+ try {
+ if (oDates != null) {
+ client.setQueryParams("yyyymm="+oDates);
+ }
+ Future<History> fh = client.read("/authz/hist/role/"+oName,gui.getDF(History.class));
+ if (fh.get(AAF_GUI.TIMEOUT)) {
+ tt.done();
+ tt = trans.start("Load History Data", Env.SUB);
+ List<Item> histItems = fh.value.getItem();
+
+ java.util.Collections.sort(histItems, new Comparator<Item>() {
+ @Override
+ public int compare(Item o1, Item o2) {
+ return o2.getTimestamp().compare(o1.getTimestamp());
+ }
+ });
+
+ for (Item i : histItems) {
+ String user = i.getUser();
+ AbsCell userCell = (user.endsWith(CSP_ATT_COM)?
+ new RefCell(user,WEBPHONE + user.substring(0,user.indexOf('@')),false):new TextCell(user));
+
+ rv.add(new AbsCell[] {
+ new TextCell(i.getTimestamp().toGregorianCalendar().getTime().toString()),
+ userCell,
+ new TextCell(i.getMemo())
+ });
+ }
+ } else {
+ if (fh.code()==403) {
+ rv.add(new AbsCell[] {new TextCell("You may not view History of Permission [" + oName + "]", "colspan = 3", "class=center")});
+ } else {
+ rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***", "colspan = 3", "class=center")});
+ }
+ }
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,msg);
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ }
+ }
+ return rv;
+ }
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RolesShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RolesShow.java
new file mode 100644
index 00000000..071666d0
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RolesShow.java
@@ -0,0 +1,144 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.auth.gui.Table.Cells;
+import org.onap.aaf.auth.gui.table.AbsCell;
+import org.onap.aaf.auth.gui.table.RefCell;
+import org.onap.aaf.auth.gui.table.TableData;
+import org.onap.aaf.auth.gui.table.TextCell;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Chrono;
+
+import aaf.v2_0.UserRole;
+import aaf.v2_0.UserRoles;
+
+
+/**
+ * Page content for My Roles
+ *
+ * @author Jonathan
+ *
+ */
+public class RolesShow extends Page {
+ public static final String HREF = "/gui/myroles";
+ private static final String DATE_TIME_FORMAT = "yyyy-MM-dd";
+ private static SimpleDateFormat expiresDF;
+
+ static {
+ expiresDF = new SimpleDateFormat(DATE_TIME_FORMAT);
+ }
+
+ public RolesShow(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, "MyRoles",HREF, NO_FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new Table<AAF_GUI,AuthzTrans>("Roles",gui.env.newTransNoAvg(),new Model(), "class=std"));
+ }
+
+ /**
+ * Implement the Table Content for Permissions by User
+ *
+ * @author Jonathan
+ *
+ */
+ private static class Model extends TableData<AAF_GUI,AuthzTrans> {
+ private static final String[] headers = new String[] {"Role","Expires","Remediation","Actions"};
+
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+ @Override
+ public Cells get(final AuthzTrans trans, final AAF_GUI gui) {
+ Cells rv = Cells.EMPTY;
+
+ try {
+ rv = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Cells>() {
+ @Override
+ public Cells code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>();
+ TimeTaken tt = trans.start("AAF Roles by User",Env.REMOTE);
+ try {
+ Future<UserRoles> fur = client.read("/authz/userRoles/user/"+trans.user(),gui.getDF(UserRoles.class));
+ if (fur.get(5000)) {
+ if(fur.value != null) for (UserRole u : fur.value.getUserRole()) {
+ if(u.getExpires().compare(Chrono.timeStamp()) < 0) {
+ AbsCell[] sa = new AbsCell[] {
+ new TextCell(u.getRole() + "*", "class=expired"),
+ new TextCell(expiresDF.format(u.getExpires().toGregorianCalendar().getTime()),"class=expired"),
+ new RefCell("Extend",
+ UserRoleExtend.HREF + "?user="+trans.user()+"&role="+u.getRole(),
+ false,
+ new String[]{"class=expired"}),
+ new RefCell("Remove",
+ UserRoleRemove.HREF + "?user="+trans.user()+"&role="+u.getRole(),
+ false,
+ new String[]{"class=expired"})
+
+ };
+ rv.add(sa);
+ } else {
+ AbsCell[] sa = new AbsCell[] {
+ new RefCell(u.getRole(),
+ RoleDetail.HREF+"?role="+u.getRole(),
+ false),
+ new TextCell(expiresDF.format(u.getExpires().toGregorianCalendar().getTime())),
+ AbsCell.Null,
+ new RefCell("Remove",
+ UserRoleRemove.HREF + "?user="+trans.user()+"&role="+u.getRole(),
+ false)
+ };
+ rv.add(sa);
+ }
+ }
+ }
+
+ } finally {
+ tt.done();
+ }
+ return new Cells(rv,null);
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ }
+ return rv;
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleExtend.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleExtend.java
new file mode 100644
index 00000000..c0ba16da
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleExtend.java
@@ -0,0 +1,99 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class UserRoleExtend extends Page {
+ public static final String HREF = "/gui/urExtend";
+ static final String NAME = "Extend User Role";
+ static final String fields[] = {"user","role"};
+
+ public UserRoleExtend(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME, HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final Slot sUser = gui.env.slot(NAME+".user");
+ final Slot sRole = gui.env.slot(NAME+".role");
+
+
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final String user = trans.get(sUser, "");
+ final String role = trans.get(sRole, "");
+
+ TimeTaken tt = trans.start("Request to extend user role",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client)throws CadiException, ConnectException, APIException {
+ Future<Void> fv = client.setQueryParams("request=true").update("/authz/userRole/extend/"+user+"/"+role);
+ if(fv.get(5000)) {
+ // not sure if we'll ever hit this
+ hgen.p("Extended User ["+ user+"] in Role [" +role+"]");
+ } else {
+ if (fv.code() == 202 ) {
+ hgen.p("User ["+ user+"] in Role [" +role+"] Extension sent for Approval");
+ } else {
+ gui.writeError(trans, fv, hgen,0);
+ }
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ trans.error().log(e);
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+
+
+ }
+ });
+ }
+
+ });
+ }
+}
+
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleRemove.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleRemove.java
new file mode 100644
index 00000000..5f8adf2d
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/UserRoleRemove.java
@@ -0,0 +1,97 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Slot;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class UserRoleRemove extends Page {
+ public static final String HREF = "/gui/urRemove";
+ static final String NAME = "Remove User Role";
+ static final String fields[] = {"user","role"};
+
+ public UserRoleRemove(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env,NAME, HREF, fields,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final Slot sUser = gui.env.slot(NAME+".user");
+ final Slot sRole = gui.env.slot(NAME+".role");
+
+
+ cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() {
+ @Override
+ public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ final String user = trans.get(sUser, "");
+ final String role = trans.get(sRole, "");
+
+ TimeTaken tt = trans.start("Request a user role delete",Env.REMOTE);
+ try {
+ gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
+ @Override
+ public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
+ Future<Void> fv = client.setQueryParams("request=true").delete(
+ "/authz/userRole/"+user+"/"+role,Void.class);
+
+ if(fv.get(5000)) {
+ // not sure if we'll ever hit this
+ hgen.p("User ["+ user+"] Removed from Role [" +role+"]");
+ } else {
+ if (fv.code() == 202 ) {
+ hgen.p("User ["+ user+"] Removal from Role [" +role+"] sent for Approval");
+ } else {
+ gui.writeError(trans, fv, hgen, 0);
+ }
+ }
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ tt.done();
+ }
+ }
+ });
+ }
+
+ });
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/WebCommand.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/WebCommand.java
new file mode 100644
index 00000000..f9c57d0f
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/WebCommand.java
@@ -0,0 +1,118 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.pages;
+
+import java.io.IOException;
+
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.gui.AAF_GUI;
+import org.onap.aaf.auth.gui.BreadCrumbs;
+import org.onap.aaf.auth.gui.NamedCode;
+import org.onap.aaf.auth.gui.Page;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.DynamicCode;
+import org.onap.aaf.misc.xgen.Mark;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class WebCommand extends Page {
+ public static final String HREF = "/gui/cui";
+
+ public WebCommand(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException {
+ super(gui.env, "Web Command Client",HREF, NO_FIELDS,
+ new BreadCrumbs(breadcrumbs),
+ new NamedCode(true, "content") {
+ @Override
+ public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException {
+ hgen.leaf("p","id=help_msg")
+ .text("Questions about this page? ")
+ .leaf("a", "href="+gui.env.getProperty(AAF_URL_CUIGUI,""), "target=_blank")
+ .text("Click here")
+ .end()
+ .text(". Type 'help' below for a list of AAF commands")
+ .end()
+
+ .divID("console_and_options");
+ hgen.divID("console_area");
+ hgen.end(); //console_area
+
+ hgen.divID("options_link", "class=closed");
+ hgen.img("src=../../"+gui.theme + "/options_down.png", "onclick=handleDivHiding('options',this);",
+ "id=options_img", "alt=Options", "title=Options")
+ .end(); //options_link
+
+ hgen.divID("options");
+ cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() {
+ @Override
+ public void code(AAF_GUI state, AuthzTrans trans, Cache<HTMLGen> cache, HTMLGen xgen)
+ throws APIException, IOException {
+ switch(browser(trans,trans.env().slot(getBrowserType()))) {
+ case ie:
+ case ieOld:
+ // IE doesn't support file save
+ break;
+ default:
+ xgen.img("src=../../"+gui.theme+"/AAFdownload.png", "onclick=saveToFile();",
+ "alt=Save log to file", "title=Save log to file");
+ }
+// xgen.img("src=../../"+gui.theme+"/AAFemail.png", "onclick=emailLog();",
+// "alt=Email log to me", "title=Email log to me");
+ xgen.img("src=../../"+gui.theme+"/AAF_font_size.png", "onclick=handleDivHiding('text_slider',this);",
+ "id=fontsize_img", "alt=Change text size", "title=Change text size");
+ xgen.img("src=../../"+gui.theme+"/AAF_details.png", "onclick=selectOption(this,0);",
+ "id=details_img", "alt=Turn on/off details mode", "title=Turn on/off details mode");
+ xgen.img("src=../../"+gui.theme+"/AAF_maximize.png", "onclick=maximizeConsole(this);",
+ "id=maximize_img", "alt=Maximize Console Window", "title=Maximize Console Window");
+ }
+ });
+ hgen.divID("text_slider");
+ hgen.tagOnly("input", "type=button", "class=change_font", "onclick=buttonChangeFontSize('dec')", "value=-")
+ .tagOnly("input", "id=text_size_slider", "type=range", "min=75", "max=200", "value=100",
+ "oninput=changeFontSize(this.value)", "onchange=changeFontSize(this.value)", "title=Change Text Size")
+ .tagOnly("input", "type=button", "class=change_font", "onclick=buttonChangeFontSize('inc')", "value=+")
+ .end(); //text_slider
+
+ hgen.end(); //options
+ hgen.end(); //console_and_options
+
+ hgen.divID("input_area");
+ hgen.tagOnly("input", "type=text", "id=command_field",
+ "autocomplete=off", "autocorrect=off", "autocapitalize=off", "spellcheck=false",
+ "onkeypress=keyPressed()", "placeholder=Type your AAFCLI commands here", "autofocus")
+ .tagOnly("input", "id=submit", "type=button", "value=Submit",
+ "onclick=http('put','../../gui/cui',getCommand(),callCUI);")
+ .end();
+
+ Mark callCUI = new Mark();
+ hgen.js(callCUI);
+ hgen.text("function callCUI(resp) {")
+ .text("moveCommandToDiv();")
+ .text("printResponse(resp);")
+ .text("}");
+ hgen.end(callCUI);
+
+ }
+ });
+
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/AbsCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/AbsCell.java
new file mode 100644
index 00000000..6d95d7d8
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/AbsCell.java
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public abstract class AbsCell {
+ public static final AbsCell[] HLINE = new AbsCell[0];
+ private static final String[] NONE = new String[0];
+ protected static final String[] CENTER = new String[]{"class=center"};
+ protected static final String[] LEFT = new String[]{"class=left"};
+ protected static final String[] RIGHT = new String[]{"class=right"};
+
+ /**
+ * Write Cell Data with HTMLGen generator
+ * @param hgen
+ */
+ public abstract void write(HTMLGen hgen);
+
+ public final static AbsCell Null = new AbsCell() {
+ @Override
+ public void write(final HTMLGen hgen) {
+ }
+ };
+
+ public String[] attrs() {
+ return NONE;
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/ButtonCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/ButtonCell.java
new file mode 100644
index 00000000..986c90af
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/ButtonCell.java
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class ButtonCell extends AbsCell {
+ private String[] attrs;
+
+ public ButtonCell(String value, String ... attributes) {
+ attrs = new String[2+attributes.length];
+ attrs[0]="type=button";
+ attrs[1]="value="+value;
+ System.arraycopy(attributes, 0, attrs, 2, attributes.length);
+ }
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.incr("input",true,attrs).end();
+
+ }
+
+ @Override
+ public String[] attrs() {
+ return AbsCell.CENTER;
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/CheckBoxCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/CheckBoxCell.java
new file mode 100644
index 00000000..4c723d4a
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/CheckBoxCell.java
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class CheckBoxCell extends AbsCell {
+ public enum ALIGN{ left, right, center };
+ private String[] attrs;
+ private ALIGN align;
+
+ public CheckBoxCell(String name, ALIGN align, String value, String ... attributes) {
+ this.align = align;
+ attrs = new String[3 + attributes.length];
+ attrs[0]="type=checkbox";
+ attrs[1]="name="+name;
+ attrs[2]="value="+value;
+ System.arraycopy(attributes, 0, attrs, 3, attributes.length);
+ }
+
+ public CheckBoxCell(String name, String value, String ... attributes) {
+ this.align = ALIGN.center;
+ attrs = new String[3 + attributes.length];
+ attrs[0]="type=checkbox";
+ attrs[1]="name="+name;
+ attrs[2]="value="+value;
+ System.arraycopy(attributes, 0, attrs, 3, attributes.length);
+ }
+
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.tagOnly("input",attrs);
+ }
+
+ @Override
+ public String[] attrs() {
+ switch(align) {
+ case left:
+ return AbsCell.LEFT;
+ case right:
+ return AbsCell.RIGHT;
+ case center:
+ default:
+ return AbsCell.CENTER;
+ }
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RadioCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RadioCell.java
new file mode 100644
index 00000000..9f092105
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RadioCell.java
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class RadioCell extends AbsCell {
+ private String[] attrs;
+
+ public RadioCell(String name, String radioClass, String value, String ... attributes) {
+ attrs = new String[4 + attributes.length];
+ attrs[0]="type=radio";
+ attrs[1]="name="+name;
+ attrs[2]="class="+radioClass;
+ attrs[3]="value="+value;
+ System.arraycopy(attributes, 0, attrs, 4, attributes.length);
+
+ }
+
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.tagOnly("input",attrs);
+ }
+
+ @Override
+ public String[] attrs() {
+ return AbsCell.CENTER;
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RefCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RefCell.java
new file mode 100644
index 00000000..7dc14c81
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/RefCell.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.A;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+/**
+ * Write a Reference Link into a Cell
+ * @author Jonathan
+ *
+ */
+public class RefCell extends AbsCell {
+ public final String name;
+ public final String[] str;
+
+ public RefCell(String name, String href, boolean newWindow, String... attributes) {
+ this.name = name;
+ if(newWindow) {
+ str = new String[attributes.length+2];
+ str[attributes.length]="target=_blank";
+ } else {
+ str = new String[attributes.length+1];
+ }
+ str[0]="href="+href;
+ System.arraycopy(attributes, 0, str, 1, attributes.length);
+
+ }
+
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.leaf(A,str).text(name);
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TableData.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TableData.java
new file mode 100644
index 00000000..731d425e
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TableData.java
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.auth.gui.Table;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.Trans;
+import org.onap.aaf.misc.xgen.Cache;
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+import org.onap.aaf.misc.xgen.html.State;
+
+public abstract class TableData<S extends State<Env>, TRANS extends Trans> implements Table.Data<S,TRANS>{
+ public static final String[] headers = new String[0];
+
+ /* (non-Javadoc)
+ * @see org.onap.aaf.auth.gui.Table.Data#prefix(org.onap.aaf.misc.xgen.html.State, com.att.inno.env.Trans, org.onap.aaf.misc.xgen.Cache, org.onap.aaf.misc.xgen.html.HTMLGen)
+ */
+ @Override
+ public void prefix(final S state, final TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aaf.auth.gui.Table.Data#postfix(org.onap.aaf.misc.xgen.html.State, com.att.inno.env.Trans, org.onap.aaf.misc.xgen.Cache, org.onap.aaf.misc.xgen.html.HTMLGen)
+ */
+ @Override
+ public void postfix(final S state, final TRANS trans, final Cache<HTMLGen> cache, final HTMLGen hgen) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aaf.auth.gui.Table.Data#headers()
+ */
+ @Override
+ public String[] headers() {
+ return headers;
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextAndRefCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextAndRefCell.java
new file mode 100644
index 00000000..036c8b7f
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextAndRefCell.java
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import static org.onap.aaf.misc.xgen.html.HTMLGen.A;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+public class TextAndRefCell extends RefCell {
+
+ private String text;
+
+ public TextAndRefCell(String text, String name, String href, boolean newWindow, String[] attributes) {
+ super(name, href, newWindow, attributes);
+ this.text = text;
+ }
+
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.text(text);
+ hgen.leaf(A,str).text(name);
+ }
+
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextCell.java
new file mode 100644
index 00000000..e20367a7
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextCell.java
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+/**
+ * Write Simple Text into a Cell
+ * @author Jonathan
+ *
+ */
+public class TextCell extends AbsCell {
+ public final String name;
+ private String[] attrs;
+
+ public TextCell(String name, String... attributes) {
+ attrs = attributes;
+ this.name = name;
+ }
+
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.text(name);
+ }
+
+ @Override
+ public String[] attrs() {
+ return attrs;
+ }
+}
diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextInputCell.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextInputCell.java
new file mode 100644
index 00000000..4a4f757c
--- /dev/null
+++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/table/TextInputCell.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.gui.table;
+
+import org.onap.aaf.misc.xgen.html.HTMLGen;
+
+/**
+ * Create an Input Cell for Text
+ * @author Jonathan
+ *
+ */
+public class TextInputCell extends AbsCell {
+ private static final String[] NULL_ATTRS=new String[0];
+ private String[] attrs;
+
+ public TextInputCell(String name, String textClass, String value, String ... attributes) {
+ attrs = new String[5 + attributes.length];
+ attrs[0]="type=text";
+ attrs[1]="name="+name;
+ attrs[2]="class="+textClass;
+ attrs[3]="value="+value;
+ attrs[4]="style=font-size:100%;";
+ System.arraycopy(attributes, 0, attrs, 5, attributes.length);
+ }
+
+ @Override
+ public void write(HTMLGen hgen) {
+ hgen.tagOnly("input",attrs);
+ }
+
+ @Override
+ public String[] attrs() {
+ return NULL_ATTRS;
+ }
+}