diff options
author | Instrumental <jcgmisc@stl.gathman.org> | 2018-03-26 13:51:48 -0700 |
---|---|---|
committer | Instrumental <jcgmisc@stl.gathman.org> | 2018-03-26 13:52:07 -0700 |
commit | 71037c39a37d3549dcfe31926832a657744fbe05 (patch) | |
tree | 78911b2b5e86e4e44228f7a27b3a8cd954b7f3e2 /auth/auth-gui/src | |
parent | a20accc73189d8e5454cd26049c0e6fae75da16f (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')
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("&"); + } + 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()+ + "&machine="+arti.getMachine() + + "&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+ + "&ns="+ns+ + "&date="+u.getExpires().toXMLFormat() + + "&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+"&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+"&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+"&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() + + "&instance=" + fields[1].trim() + + "&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() + +"&instance="+p.getInstance() + +"&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; + } +} |