diff options
author | sg481n <sg481n@att.com> | 2017-08-03 17:27:34 -0400 |
---|---|---|
committer | sg481n <sg481n@att.com> | 2017-08-03 17:27:34 -0400 |
commit | 43854a9e3310ff7a92257d16c4fc0a8321eaec68 (patch) | |
tree | 46af936c5da4f9c60d7d63dade5c61a8fd5ef9f4 /authz-gui/src | |
parent | f691a8b8dfc9eea4c6b3bfa45ea60f07ad347e69 (diff) |
[AAF-21] Initial code import
Change-Id: I63d7d499bbd46f500b5f5a4db966166f613f327a
Signed-off-by: sg481n <sg481n@att.com>
Diffstat (limited to 'authz-gui/src')
45 files changed, 5251 insertions, 0 deletions
diff --git a/authz-gui/src/main/config/authGUI.props b/authz-gui/src/main/config/authGUI.props new file mode 100644 index 00000000..d90e4406 --- /dev/null +++ b/authz-gui/src/main/config/authGUI.props @@ -0,0 +1,34 @@ +## +## AUTHZ GUI (authz-gui) Properties +## + +hostname=_HOSTNAME_ + +## DISCOVERY (DME2) Parameters on the Command Line +AFT_LATITUDE=_AFT_LATITUDE_ +AFT_LONGITUDE=_AFT_LONGITUDE_ +AFT_ENVIRONMENT=_AFT_ENVIRONMENT_ +DEPLOYED_VERSION=_ARTIFACT_VERSION_ + +## Pull in common/security properties + +cadi_prop_files=_COMMON_DIR_/com.att.aaf.common.props;_COMMON_DIR_/com.att.aaf.props + +##DME2 related parameters +DMEServiceName=service=com.att.authz.authz-gui/version=_MAJOR_VER_._MINOR_VER_._PATCH_VER_/envContext=_ENV_CONTEXT_/routeOffer=_ROUTE_OFFER_ +AFT_DME2_PORT_RANGE=_AUTHZ_GUI_PORT_RANGE_ + +# Turn on both AAF TAF & LUR 2.0 +aaf_url=https://DME2RESOLVE/service=com.att.authz.AuthorizationService/version=_MAJOR_VER_._MINOR_VER_/envContext=_ENV_CONTEXT_/routeOffer=_ROUTE_OFFER_ + +## URLs +aaf_url.gui_onboard=https://wiki.web.att.com/display/aaf/OnBoarding +aaf_url.aaf_help=http://wiki.web.att.com/display/aaf +aaf_url.cadi_help=http://wiki.web.att.com/display/cadi +aaf_tools=swm,scamper,dme2,soacloud +aaf_url.tool.swm=http://wiki.web.att.com/display/swm +aaf_url.tool.scamper=https://wiki.web.att.com/display/scamper/Home +aaf_url.tool.soacloud=https://wiki.web.att.com/display/soacloud/SOA+Cloud+Management+Platform +aaf_url.tool.dme2=https://wiki.web.att.com/display/soacloud/User+Guide+-+DME2 + + diff --git a/authz-gui/src/main/config/log4j.properties b/authz-gui/src/main/config/log4j.properties new file mode 100644 index 00000000..e1c9db74 --- /dev/null +++ b/authz-gui/src/main/config/log4j.properties @@ -0,0 +1,57 @@ +############################################################################### +# Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +############################################################################### +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# +log4j.appender.INIT=org.apache.log4j.DailyRollingFileAppender +log4j.appender.INIT.File=_LOG_DIR_/${LOG4J_FILENAME_init} +log4j.appender.INIT.DatePattern='.'yyyy-MM-dd +#log4j.appender.INIT.MaxFileSize=_MAX_LOG_FILE_SIZE_ +#log4j.appender.INIT.MaxBackupIndex=_MAX_LOG_FILE_BACKUP_COUNT_ +log4j.appender.INIT.layout=org.apache.log4j.PatternLayout +log4j.appender.INIT.layout.ConversionPattern=%d %p [%c] %m %n + +log4j.appender.GUI=org.apache.log4j.DailyRollingFileAppender +log4j.appender.GUI.File=_LOG_DIR_/${LOG4J_FILENAME_gui} +log4j.appender.GUI.DatePattern='.'yyyy-MM-dd +#log4j.appender.GUI.MaxFileSize=_MAX_LOG_FILE_SIZE_ +#log4j.appender.GUI.MaxBackupIndex=_MAX_LOG_FILE_BACKUP_COUNT_ +log4j.appender.GUI.layout=org.apache.log4j.PatternLayout +log4j.appender.GUI.layout.ConversionPattern=%d %p [%c] %m %n + +log4j.appender.AUDIT=org.apache.log4j.DailyRollingFileAppender +log4j.appender.AUDIT.File=_LOG_DIR_/${LOG4J_FILENAME_audit} +log4j.appender.AUDIT.DatePattern='.'yyyy-MM-dd +#log4j.appender.GUI.MaxFileSize=_MAX_LOG_FILE_SIZE_ +#log4j.appender.GUI.MaxBackupIndex=_MAX_LOG_FILE_BACKUP_COUNT_ +log4j.appender.AUDIT.layout=org.apache.log4j.PatternLayout +log4j.appender.AUDIT.layout.ConversionPattern=%d %p [%c] %m %n + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] %m %n + +# General Apache libraries +log4j.rootLogger=WARN +log4j.logger.org.apache=WARN,INIT +log4j.logger.dme2=WARN,INIT +log4j.logger.init=INFO,INIT +log4j.logger.gui=_LOG4J_LEVEL_,GUI +log4j.logger.audit=INFO,AUDIT + diff --git a/authz-gui/src/main/config/lrm-authz-gui.xml b/authz-gui/src/main/config/lrm-authz-gui.xml new file mode 100644 index 00000000..f9a45e94 --- /dev/null +++ b/authz-gui/src/main/config/lrm-authz-gui.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + --> + +<ns2:ManagedResourceList xmlns:ns2="http://scld.att.com/lrm/util" xmlns="http://scld.att.com/lrm/commontypes" xmlns:ns3="http://scld.att.com/lrm/types"> + <ns2:ManagedResource> + <ResourceDescriptor> + <ResourceName>com.att.authz._ARTIFACT_ID_</ResourceName> + <ResourceVersion> + <Major>_MAJOR_VER_</Major> + <Minor>_MINOR_VER_</Minor> + <Patch>_PATCH_VER_</Patch> + </ResourceVersion> + <RouteOffer>_ROUTE_OFFER_</RouteOffer> + </ResourceDescriptor> + <ResourceType>Java</ResourceType> + <ResourcePath>com.att.authz.gui.AuthGUI</ResourcePath> + <ResourceProps> + <Tag>process.workdir</Tag> + <Value>_ROOT_DIR_</Value> + </ResourceProps> + <ResourceProps> + <Tag>jvm.version</Tag> + <Value>1.8</Value> + </ResourceProps> + <ResourceProps> + <Tag>jvm.args</Tag> + <Value>-DAFT_LATITUDE=_AFT_LATITUDE_ -DAFT_LONGITUDE=_AFT_LONGITUDE_ -DAFT_ENVIRONMENT=_AFT_ENVIRONMENT_ -Dplatform=_SCLD_PLATFORM_ -Dcom.sun.jndi.ldap.connect.pool.maxsize=20 -Dcom.sun.jndi.ldap.connect.pool.prefsize=10 -Dcom.sun.jndi.ldap.connect.pool.timeout=3000 </Value> + </ResourceProps> + <ResourceProps> + <Tag>jvm.classpath</Tag> + <Value>_ROOT_DIR_/etc:_ROOT_DIR_/lib/*:</Value> + </ResourceProps> + <ResourceProps> + <Tag>jvm.heap.min</Tag> + <Value>512m</Value> + </ResourceProps> + <ResourceProps> + <Tag>jvm.heap.max</Tag> + <Value>2048m</Value> + </ResourceProps> + <ResourceProps> + <Tag>start.class</Tag> + <Value>com.att.authz.gui.AuthGUI</Value> + </ResourceProps> + <ResourceProps> + <Tag>stdout.redirect</Tag> + <Value>_ROOT_DIR_/logs/SystemOut.log</Value> + </ResourceProps> + <ResourceProps> + <Tag>stderr.redirect</Tag> + <Value>_ROOT_DIR_/logs/SystemErr.log</Value> + </ResourceProps> + <ResourceOSID>aft</ResourceOSID> + <ResourceStartType>AUTO</ResourceStartType> + <ResourceStartPriority>3</ResourceStartPriority> + <ResourceMinCount>_RESOURCE_MIN_COUNT_</ResourceMinCount> + <ResourceMaxCount>_RESOURCE_MAX_COUNT_</ResourceMaxCount> + <ResourceRegistration>_RESOURCE_REGISTRATION_</ResourceRegistration> + <ResourceSWMComponent>com.att.authz:_ARTIFACT_ID_</ResourceSWMComponent> + <ResourceSWMComponentVersion>_ARTIFACT_VERSION_</ResourceSWMComponentVersion> + </ns2:ManagedResource> +</ns2:ManagedResourceList> diff --git a/authz-gui/src/main/java/com/att/authz/cui/CUI.java b/authz-gui/src/main/java/com/att/authz/cui/CUI.java new file mode 100644 index 00000000..2f78ae24 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/cui/CUI.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.cui; + +import java.io.PrintWriter; +import java.security.Principal; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.cadi.config.Config; +import com.att.cadi.http.HTransferSS; +import com.att.cmd.AAFcli; +import com.att.cssa.rserv.HttpCode; + +public class CUI extends HttpCode<AuthzTrans, Void> { + private final AuthGUI gui; + public CUI(AuthGUI 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); + } + + Principal p = trans.getUserPrincipal(); + trans.env().setProperty(Config.AAF_DEFAULT_REALM, trans.env().getProperty(Config.AAF_DEFAULT_REALM,Config.getDefaultRealm())); + AAFcli aafcli = new AAFcli(trans.env(), pw, + gui.aafCon.hman(), + gui.aafCon.securityInfo(), new HTransferSS(p,AuthGUI.app, + gui.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(); + } + + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/AuthGUI.java b/authz-gui/src/main/java/com/att/authz/gui/AuthGUI.java new file mode 100644 index 00000000..3e28b83a --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/AuthGUI.java @@ -0,0 +1,319 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import static com.att.cssa.rserv.HttpMethods.GET; +import static com.att.cssa.rserv.HttpMethods.POST; +import static com.att.cssa.rserv.HttpMethods.PUT; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Properties; + +import com.att.aft.dme2.api.DME2Exception; +import com.att.aft.dme2.api.DME2Manager; +import com.att.aft.dme2.api.DME2Server; +import com.att.aft.dme2.api.DME2ServerProperties; +import com.att.aft.dme2.api.DME2ServiceHolder; +import com.att.aft.dme2.api.util.DME2FilterHolder; +import com.att.aft.dme2.api.util.DME2FilterHolder.RequestDispatcherType; +import com.att.aft.dme2.api.util.DME2ServletHolder; +import com.att.authz.common.Define; +import com.att.authz.cui.CUI; +import com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.env.AuthzTransFilter; +import com.att.authz.env.AuthzTransOnlyFilter; +import com.att.authz.gui.pages.ApiDocs; +import com.att.authz.gui.pages.ApiExample; +import com.att.authz.gui.pages.ApprovalAction; +import com.att.authz.gui.pages.ApprovalForm; +import com.att.authz.gui.pages.Home; +import com.att.authz.gui.pages.LoginLanding; +import com.att.authz.gui.pages.LoginLandingAction; +import com.att.authz.gui.pages.NsDetail; +import com.att.authz.gui.pages.NsHistory; +import com.att.authz.gui.pages.NsInfoAction; +import com.att.authz.gui.pages.NsInfoForm; +import com.att.authz.gui.pages.NssShow; +import com.att.authz.gui.pages.PassChangeAction; +import com.att.authz.gui.pages.PassChangeForm; +import com.att.authz.gui.pages.PendingRequestsShow; +import com.att.authz.gui.pages.PermDetail; +import com.att.authz.gui.pages.PermGrantAction; +import com.att.authz.gui.pages.PermGrantForm; +import com.att.authz.gui.pages.PermHistory; +import com.att.authz.gui.pages.PermsShow; +import com.att.authz.gui.pages.RequestDetail; +import com.att.authz.gui.pages.RoleDetail; +import com.att.authz.gui.pages.RoleHistory; +import com.att.authz.gui.pages.RolesShow; +import com.att.authz.gui.pages.UserRoleExtend; +import com.att.authz.gui.pages.UserRoleRemove; +import com.att.authz.gui.pages.WebCommand; +import com.att.authz.org.OrganizationFactory; +import com.att.authz.server.AbsServer; +import com.att.cadi.CadiException; +import com.att.cadi.aaf.v2_0.AAFTrustChecker; +import com.att.cadi.client.Future; +import com.att.cadi.config.Config; +import com.att.cssa.rserv.CachingFileAccess; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.rosetta.env.RosettaDF; +import com.att.xgen.html.HTMLGen; +import com.att.xgen.html.State; + +import aaf.v2_0.Api; +import aaf.v2_0.Approvals; +import aaf.v2_0.CredRequest; +import aaf.v2_0.Error; +import aaf.v2_0.History; +import aaf.v2_0.Nss; +import aaf.v2_0.Perms; +import aaf.v2_0.RolePermRequest; +import aaf.v2_0.Roles; +import aaf.v2_0.UserRoles; +import aaf.v2_0.Users; + +public class AuthGUI extends AbsServer implements State<Env>{ + public static final int TIMEOUT = 60000; + public static final String app = "AAF GUI"; + + public RosettaDF<Perms> permsDF; + public RosettaDF<Roles> rolesDF; + public RosettaDF<Users> usersDF; + public RosettaDF<UserRoles> userrolesDF; + public RosettaDF<CredRequest> credReqDF; + public RosettaDF<RolePermRequest> rolePermReqDF; + public RosettaDF<Approvals> approvalsDF; + public RosettaDF<Nss> nssDF; + public RosettaDF<Api> apiDF; + public RosettaDF<Error> errDF; + public RosettaDF<History> historyDF; + + public final AuthzEnv env; + public final Slot slot_httpServletRequest; + + public AuthGUI(final AuthzEnv env) throws CadiException, GeneralSecurityException, IOException, APIException { + super(env,app); + this.env = env; + + env.setLog4JNames("log4j.properties","authz","gui","audit","init","trace "); + OrganizationFactory.setDefaultOrg(env, "com.att.authz.org.att.ATT"); + + + slot_httpServletRequest = env.slot("HTTP_SERVLET_REQUEST"); + + permsDF = env.newDataFactory(Perms.class); + rolesDF = env.newDataFactory(Roles.class); +// credsDF = env.newDataFactory(Cred.class); + usersDF = env.newDataFactory(Users.class); + userrolesDF = env.newDataFactory(UserRoles.class); + credReqDF = env.newDataFactory(CredRequest.class); + rolePermReqDF = env.newDataFactory(RolePermRequest.class); + approvalsDF = env.newDataFactory(Approvals.class); + nssDF = env.newDataFactory(Nss.class); + apiDF = env.newDataFactory(Api.class); + errDF = env.newDataFactory(Error.class); + historyDF = env.newDataFactory(History.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, 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)); + + // Password Change Screens + final Page pwc = new Display(this, GET, new PassChangeForm(this, start)).page(); + new Display(this, POST, new PassChangeAction(this, start, pwc)); + + // 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,"/theme/:key", new CachingFileAccess<AuthzTrans>(env, + CachingFileAccess.CFA_WEB_DIR,"theme")); + /////////////////////// + } + + public static void main(String[] args) { + setup(AuthGUI.class, "authGUI.props"); + } + + /** + * Start up AuthzAPI as DME2 Service + * @param env + * @param props + * @throws DME2Exception + * @throws CadiException + */ + public void startDME2(Properties props) throws DME2Exception, CadiException { + + DME2Manager dme2 = new DME2Manager("AAF GUI DME2Manager", props); + DME2ServiceHolder svcHolder; + List<DME2ServletHolder> slist = new ArrayList<DME2ServletHolder>(); + svcHolder = new DME2ServiceHolder(); + String serviceName = env.getProperty("DMEServiceName",null); + if(serviceName!=null) { + svcHolder.setServiceURI(serviceName); + svcHolder.setManager(dme2); + svcHolder.setContext("/"); + + + DME2ServletHolder srvHolder = new DME2ServletHolder(this, new String[]{"/gui"}); + srvHolder.setContextPath("/*"); + slist.add(srvHolder); + + EnumSet<RequestDispatcherType> edlist = EnumSet.of( + RequestDispatcherType.REQUEST, + RequestDispatcherType.FORWARD, + RequestDispatcherType.ASYNC + ); + + /////////////////////// + // Apply Filters + /////////////////////// + List<DME2FilterHolder> flist = new ArrayList<DME2FilterHolder>(); + + // Secure all GUI interactions with AuthzTransFilter + flist.add(new DME2FilterHolder(new AuthzTransFilter(env, aafCon, new AAFTrustChecker( + env.getProperty(Config.CADI_TRUST_PROP, Config.CADI_USER_CHAIN), + Define.ROOT_NS + ".mechid|"+Define.ROOT_COMPANY+"|trust" + )),"/gui/*", edlist)); + + // Don't need security for display Artifacts or login page + AuthzTransOnlyFilter atof; + flist.add(new DME2FilterHolder(atof =new AuthzTransOnlyFilter(env),"/theme/*", edlist)); + flist.add(new DME2FilterHolder(atof,"/js/*", edlist)); + flist.add(new DME2FilterHolder(atof,"/login/*", edlist)); + + svcHolder.setFilters(flist); + svcHolder.setServletHolders(slist); + + DME2Server dme2svr = dme2.getServer(); +// dme2svr.setGracefulShutdownTimeMs(1000); + + env.init().log("Starting AAF GUI with Jetty/DME2 server..."); + dme2svr.start(); + DME2ServerProperties dsprops = dme2svr.getServerProperties(); + try { +// if(env.getProperty("NO_REGISTER",null)!=null) + dme2.bindService(svcHolder); + env.init().log("DME2 is available as HTTP"+(dsprops.isSslEnable()?"/S":""),"on port:",dsprops.getPort()); + + while(true) { // Per DME2 Examples... + Thread.sleep(5000); + } + } catch(InterruptedException e) { + env.init().log("AAF Jetty Server interrupted!"); + } catch(Exception e) { // Error binding service doesn't seem to stop DME2 or Process + env.init().log(e,"DME2 Initialization Error"); + dme2svr.stop(); + System.exit(1); + } + } else { + env.init().log("Properties must contain DMEServiceName"); + } + } + + + public AuthzEnv env() { + return env; + } + + /** + * Derive API Error Class from AAF Response (future) + */ + public Error getError(AuthzTrans trans, Future<?> fp) { +// try { + String text = fp.body(); + Error err = new Error(); + err.setMessageId(Integer.toString(fp.code())); + if(text==null || text.length()==0) { + err.setText("**No Message**"); + } else { + err.setText(fp.body()); + } + return err; +// } catch (APIException e) { +// Error err = new Error(); +// err.setMessageId(Integer.toString(fp.code())); +// err.setText("Could not obtain response from AAF Message: " + e.getMessage()); +// return err; +// } + } + + public void writeError(AuthzTrans trans, Future<?> fp, HTMLGen hgen) { + Error err = getError(trans,fp); + + String messageBody = err.getText(); + List<String> vars = err.getVariables(); + for (int varCounter=0;varCounter<vars.size();) { + String var = vars.get(varCounter++); + if (messageBody.indexOf("%" + varCounter) >= 0) { + messageBody = messageBody.replace("%" + varCounter, var); + } + } + + String msg = "[" + err.getMessageId() + "] " + messageBody; + if(hgen!=null) { + hgen.text(msg); + } + trans.checkpoint("AAF Error: " + msg); + } + +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/BreadCrumbs.java b/authz-gui/src/main/java/com/att/authz/gui/BreadCrumbs.java new file mode 100644 index 00000000..b18b563b --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/BreadCrumbs.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import static com.att.xgen.html.HTMLGen.A; +import static com.att.xgen.html.HTMLGen.LI; +import static com.att.xgen.html.HTMLGen.UL; + +import java.io.IOException; + +import com.att.inno.env.APIException; +import com.att.xgen.Cache; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + +public class BreadCrumbs extends NamedCode { + private Page[] breadcrumbs; + + public BreadCrumbs(Page ... pages) { + super(false,"breadcrumbs"); + breadcrumbs = pages; + } + + @Override + public void code(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + // BreadCrumbs + Mark mark = new Mark(); + hgen.incr(mark, UL); + for(Page p : breadcrumbs) { + hgen.incr(LI,true) + .leaf(A,"href="+p.url()).text(p.name()) + .end(2); + } + hgen.end(mark); + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/Controls.java b/authz-gui/src/main/java/com/att/authz/gui/Controls.java new file mode 100644 index 00000000..c99c9ff2 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/Controls.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import java.io.IOException; + +import com.att.inno.env.APIException; +import com.att.xgen.Cache; +import com.att.xgen.html.HTMLGen; + +public class Controls extends NamedCode { + public Controls() { + super(false,"controls"); + } + + @Override + public void code(Cache<HTMLGen> cache, 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/authz-gui/src/main/java/com/att/authz/gui/Display.java b/authz-gui/src/main/java/com/att/authz/gui/Display.java new file mode 100644 index 00000000..5ce77e95 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/Display.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.att.authz.env.AuthzTrans; +import com.att.cssa.rserv.HttpCode; +import com.att.cssa.rserv.HttpMethods; +import com.att.inno.env.Slot; + +public class Display { + private final Page get; + public Display(final AuthGUI 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,AuthGUI>(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 + String field=fields[i].substring(0, idx); + String[] array = new String[30]; + for(Enumeration<String> names = req.getParameterNames(); names.hasMoreElements();) { + String key = names.nextElement(); + if(key.subSequence(0, idx).equals(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,AuthGUI>(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/authz-gui/src/main/java/com/att/authz/gui/Form.java b/authz-gui/src/main/java/com/att/authz/gui/Form.java new file mode 100644 index 00000000..3443c2c4 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/Form.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import java.io.IOException; + +import com.att.inno.env.APIException; +import com.att.xgen.Cache; +import com.att.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.idattrs()); + this.content = content; + preamble=null; + idattrs = content.idattrs(); + } + + public Form preamble(String preamble) { + this.preamble = preamble; + return this; + } + + + @Override + public void code(Cache<HTMLGen> cache, 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 com.att.authz.gui.NamedCode#idattrs() + */ + @Override + public String[] idattrs() { + return content.idattrs(); + } + +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/NamedCode.java b/authz-gui/src/main/java/com/att/authz/gui/NamedCode.java new file mode 100644 index 00000000..90e11707 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/NamedCode.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import com.att.xgen.Code; +import com.att.xgen.html.HTMLGen; + + + +public abstract class NamedCode implements Code<HTMLGen> { + public final boolean no_cache; + protected String[] idattrs; + + /* + * Mark whether this code should not be cached, and any attributes + */ + public NamedCode(final boolean no_cache, String ... idattrs) { + this.idattrs = idattrs; + this.no_cache = no_cache; + } + + /** + * Return ID and Any Attributes needed to create a "div" section of this code + * @return + */ + public String[] idattrs() { + return idattrs; + } + +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/Page.java b/authz-gui/src/main/java/com/att/authz/gui/Page.java new file mode 100644 index 00000000..8a97f0e0 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/Page.java @@ -0,0 +1,292 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import static com.att.xgen.html.HTMLGen.A; +import static com.att.xgen.html.HTMLGen.H1; +import static com.att.xgen.html.HTMLGen.LI; +import static com.att.xgen.html.HTMLGen.TITLE; +import static com.att.xgen.html.HTMLGen.UL; + +import java.io.IOException; +import java.security.Principal; + +import com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.cadi.config.Config; +import com.att.inno.env.APIException; +import com.att.inno.env.Slot; +import com.att.inno.env.util.Split; +import com.att.xgen.Cache; +import com.att.xgen.CacheGen; +import com.att.xgen.Code; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLCacheGen; +import com.att.xgen.html.HTMLGen; +import com.att.xgen.html.Imports; + +/** + * A Base "Mobile First" Page + * + * + */ +public class Page extends HTMLCacheGen { + 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 ENV_CONTEXT = "envContext"; + private static final String DME_SERVICE_NAME = "DMEServiceName"; + private static final String ROUTE_OFFER = "routeOffer"; + private static final String BROWSER_TYPE = "BROWSER_TYPE"; + + private final String bcName, bcUrl; + private final String[] fields; + + public final boolean no_cache; + + public String name() { + return bcName; + } + + public String url() { + return bcUrl; + } + + public String[] fields() { + return fields; + } + + 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)); + bcName = name; + bcUrl = url; + this.fields = fields; + // 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 final NamedCode[] content; + private final Slot browserSlot; + private final int backdots; + protected AuthzEnv env; + + public PageCode(AuthzEnv env, int backdots, final NamedCode[] content) { + this.content = content; + this.backdots = backdots; + browserSlot = env.slot(BROWSER_TYPE); + this.env = env; + } + + @Override + public void code(Cache<HTMLGen> cache, 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 + //hgen.html("manifest=../theme/aaf.appcache"); + cache.dynamic(hgen, new DynamicCode<HTMLGen,AuthGUI,AuthzTrans>() { + @Override + public void code(AuthGUI state, AuthzTrans trans, Cache<HTMLGen> cache, 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(); + Mark head = hgen.head(); + hgen.leaf(TITLE).text("AT&T Authentication/Authorization Tool").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,AuthGUI,AuthzTrans>() { + @Override + public void code(AuthGUI state, AuthzTrans trans, Cache<HTMLGen> cache, 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,AuthGUI,AuthzTrans>() { + @Override + public void code(AuthGUI state, AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen xgen) + throws APIException, IOException { + // Obtain Server Info, and print + String DMEServiceName = trans.getProperty(DME_SERVICE_NAME); + String env = DMEServiceName.substring( + DMEServiceName.indexOf(ENV_CONTEXT), + DMEServiceName.indexOf(ROUTE_OFFER) -1).split("=")[1]; + + xgen.leaf(H1).text("AT&T Auth Tool on " + env).end(); + xgen.leaf("p","id=version").text("AAF Version: " + trans.getProperty(Config.AAF_DEPLOYED_VERSION, "N/A")).end(); + + // Obtain User Info, and print + Principal p = trans.getUserPrincipal(); + String user; + if(p==null) { + user = "please choose a Login Authority"; + } else { + user = p.getName(); + } + xgen.leaf("p","id=welcome").text("Welcome, " + user).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; + NamedCode 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) + .leaf(LI).leaf(A,"href="+env.getProperty("aaf_url.aaf_help")).text("AAF WIKI").end(2) + .leaf(LI).leaf(A,"href="+env.getProperty("aaf_url.cadi_help")).text("CADI WIKI").end(2); + String tools = env.getProperty("aaf_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."+tool)).text(tool.toUpperCase() + " Help").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, "(c) 2014-6 AT&T Inc. All Rights Reserved") + .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; + } +} + diff --git a/authz-gui/src/main/java/com/att/authz/gui/Table.java b/authz-gui/src/main/java/com/att/authz/gui/Table.java new file mode 100644 index 00000000..2e20e532 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/Table.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui; + +import static com.att.xgen.html.HTMLGen.TABLE; +import static com.att.xgen.html.HTMLGen.TD; +import static com.att.xgen.html.HTMLGen.TR; + +import java.io.IOException; +import java.util.ArrayList; + +import com.att.authz.gui.table.AbsCell; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.Trans; +import com.att.inno.env.TransStore; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; +import com.att.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; + + public Table(String title, TRANS trans, Data<S,TRANS> data, String ... attrs) { + super(true,attrs); + 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) + idattrs = new String[attrs.length+1]; + idattrs[0] = title.replaceAll("\\s",""); + System.arraycopy(attrs, 0, idattrs, 1, attrs.length); + } + + @Override + public void code(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + Mark table = new Mark(); + Mark tr = new Mark(); + hgen.incr(table,TABLE) + .leaf("caption", "class=title").text(title).end() + .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); + + // Print Message from Row Gathering, if available + cache.dynamic(hgen, new DynamicCode<HTMLGen,S,TRANS>() { + @Override + public void code(S state, TRANS trans, Cache<HTMLGen> cache, 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(); + } + } + }); + } + + 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> { + public Cells get(S state,TRANS trans); + 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(S state, TRANS trans, Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + Mark tr = new Mark(); + Mark td = new Mark(); + + int alt = this.alt; + Cells cells = data.get(state, trans); + if(cells.cells.length>0) { + for(AbsCell[] row : cells.cells) { + 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); + } + } + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/ApiDocs.java b/authz-gui/src/main/java/com/att/authz/gui/pages/ApiDocs.java new file mode 100644 index 00000000..0e430009 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/ApiDocs.java @@ -0,0 +1,304 @@ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.Symm; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.cssa.rserv.HttpMethods; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.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 AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,NAME,HREF, fields, + new BreadCrumbs(breadcrumbs), + new Preamble(), + new Table<AuthGUI,AuthzTrans>("AAF API Reference",gui.env.newTransNoAvg(),new Model(), "class=std") + ); + } + + private static class Preamble extends NamedCode { + + private static final String I = "i"; + + public Preamble() { + super(false, "preamble"); + } + + @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("(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=../theme/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 + * + * + */ + private static class Model implements Table.Data<AuthGUI,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; + } + + @SuppressWarnings("unchecked") + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + ArrayList<AbsCell[]> ns = new ArrayList<AbsCell[]>(); + ArrayList<AbsCell[]> perms = new ArrayList<AbsCell[]>(); + ArrayList<AbsCell[]> roles = new ArrayList<AbsCell[]>(); + ArrayList<AbsCell[]> user = new ArrayList<AbsCell[]>(); + ArrayList<AbsCell[]> aafOnly = new ArrayList<AbsCell[]>(); + ArrayList<AbsCell[]> rv = new ArrayList<AbsCell[]>(); + + + TimeTaken tt = trans.start("AAF APIs",Env.REMOTE); + try { + gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() { + @Override + public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException { + Future<Api> fa = client.read("/api",gui.apiDF); + 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); + } + 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/authz-gui/src/main/java/com/att/authz/gui/pages/ApiExample.java b/authz-gui/src/main/java/com/att/authz/gui/pages/ApiExample.java new file mode 100644 index 00000000..d4f49d98 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/ApiExample.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.Symm; +import com.att.cadi.client.Future; +import com.att.inno.env.APIException; +import com.att.inno.env.Data.TYPE; +import com.att.inno.env.Env; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.Error; + +/** + * Detail Page for Permissions + * + * + */ +public class ApiExample extends Page { + public static final String HREF = "/gui/example/:tc"; + public static final String NAME = "APIExample"; + + public ApiExample(final AuthGUI gui, Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, NAME, HREF, 2/*backdots*/, new String[] {"API Code Example"}, + new BreadCrumbs(breadcrumbs), + new Model() + ); + } + + 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() { + super(false); + } + + @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,AuthGUI,AuthzTrans>() { + @Override + public void code(final AuthGUI gui, 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/" + typecode+"?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 { + Error err = gui.errDF.newData().in(TYPE.JSON).load(fp.body()).asObject(); + xgen.incr(HTMLGen.H3) + .textCR(2,"Error from AAF Service") + .end(); + + xgen.p("Error Code: ",err.getMessageId()) + .p(err.getText()) + .end(); + + } + + } 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/authz-gui/src/main/java/com/att/authz/gui/pages/ApprovalAction.java b/authz-gui/src/main/java/com/att/authz/gui/pages/ApprovalAction.java new file mode 100644 index 00000000..34f6f4e2 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/ApprovalAction.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.Approval; +import aaf.v2_0.Approvals; + +public class ApprovalAction extends Page { + public ApprovalAction(final AuthGUI 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(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + cache.dynamic(hgen, new DynamicCode<HTMLGen,AuthGUI, AuthzTrans>() { + @Override + public void code(final AuthGUI gui, final AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + boolean fail = true; + 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; + fail = 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.approvalsDF,apps); + if(fa.get(AuthGUI.TIMEOUT)) { + // Do Remote Call + fail2 = false; + hgen.p(total + (total==1?" Approval has":" Approvals have") + " been Saved"); + } else { + gui.writeError(trans, fa, hgen); + } + return fail2; + } + }); + } catch (Exception e) { + e.printStackTrace(); + } finally { + tt.done(); + } + } + + hgen.br(); + if(fail) { + hgen.incr("a",true,"href="+lastPage).text("Try again").end(); + } else { + hgen.incr("a",true,"href="+Home.HREF).text("Home").end(); + } + } + } + }); + } + }); + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/ApprovalForm.java b/authz-gui/src/main/java/com/att/authz/gui/pages/ApprovalForm.java new file mode 100644 index 00000000..c880932b --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/ApprovalForm.java @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Form; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.ButtonCell; +import com.att.authz.gui.table.RadioCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextAndRefCell; +import com.att.authz.gui.table.TextCell; +import com.att.authz.org.Organization; +import com.att.authz.org.Organization.Identity; +import com.att.authz.org.OrganizationFactory; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.Approval; + +public class ApprovalForm extends Page { + // Package on purpose + static final String NAME="Approvals"; + static final String HREF = "/gui/approve"; + static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id="; + static final String[] FIELDS = new String[] {"line[]","user"}; + + + public ApprovalForm(final AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,NAME,HREF, FIELDS, + + new BreadCrumbs(breadcrumbs), + new NamedCode(false, "filterByUser") { + @Override + public void code(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + cache.dynamic(hgen, new DynamicCode<HTMLGen, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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<AuthGUI,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"), + new NamedCode(false, "selectAlljs") { + @Override + public void code(Cache<HTMLGen> cache, 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 + * + * + */ + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private static final String[] headers = new String[] {"Identity","Request","Approve","Deny"}; + private static final Object THE_DOMAIN = null; + private Slot sUser; + + public Model(AuthzEnv env) { + sUser = env.slot(NAME+".user"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + 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<aaf.v2_0.Approvals> fa = client.read("/authz/approval/approver/"+trans.user(),gui.approvalsDF); + int numLeft = 0; + if(fa.get(AuthGUI.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(THE_DOMAIN)) { + approverHeader = new AbsCell[] { + new TextAndRefCell("Approvals Delegated to Me by ", currApprover, + WEBPHONE + currApproverShort, + 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; + 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 { + 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")) { + title="title=Sponsor is " + au.responsibleTo(); + } else { + title="title=" + au.fullName(); + } + } else { + title=""; + } + } + userCell = new RefCell(prevUser=user, + "" //TODO add Organization Link ability + ,title); + } + AbsCell[] sa = new AbsCell[] { + userCell, + new TextCell(appr.getMemo()), + new RadioCell("line"+ line,"approve", "approved|"+appr.getTicket()), + 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/authz-gui/src/main/java/com/att/authz/gui/pages/Home.java b/authz-gui/src/main/java/com/att/authz/gui/pages/Home.java new file mode 100644 index 00000000..0eaa25ed --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/Home.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import static com.att.xgen.html.HTMLGen.A; +import static com.att.xgen.html.HTMLGen.H3; + +import java.io.IOException; + +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.inno.env.APIException; +import com.att.xgen.Cache; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + + +public class Home extends Page { + public static final String HREF = "/gui/home"; + public Home(final AuthGUI 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=mynamespaces").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/authz-gui/src/main/java/com/att/authz/gui/pages/LoginLanding.java b/authz-gui/src/main/java/com/att/authz/gui/pages/LoginLanding.java new file mode 100644 index 00000000..1a42bfe5 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/LoginLanding.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.URLDecoder; + +import javax.servlet.http.HttpServletRequest; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.config.Config; +import com.att.inno.env.APIException; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.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 AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, NAME,HREF, fields, new NamedCode(true, "content") { + @Override + public void code(Cache<HTMLGen> cache, 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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI 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(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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/authz-gui/src/main/java/com/att/authz/gui/pages/LoginLandingAction.java b/authz-gui/src/main/java/com/att/authz/gui/pages/LoginLandingAction.java new file mode 100644 index 00000000..35a2e328 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/LoginLandingAction.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.inno.env.APIException; +import com.att.inno.env.Slot; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.html.HTMLGen; + +public class LoginLandingAction extends Page { + public LoginLandingAction(final AuthGUI 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(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + cache.dynamic(hgen, new DynamicCode<HTMLGen,AuthGUI, AuthzTrans>() { + @Override + public void code(final AuthGUI gui, final AuthzTrans trans,Cache<HTMLGen> cache, 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/authz-gui/src/main/java/com/att/authz/gui/pages/NsDetail.java b/authz-gui/src/main/java/com/att/authz/gui/pages/NsDetail.java new file mode 100644 index 00000000..7ed241d4 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/NsDetail.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; +import java.util.List; + +import com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.cmd.AAFcli; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.inno.env.util.Chrono; + +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; +import aaf.v2_0.Users; +import aaf.v2_0.Users.User; + +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 = ""; + + public NsDetail(final AuthGUI gui, Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, NAME, HREF, new String[] {"name"}, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Namespace Details",gui.env.newTransNoAvg(),new Model(gui.env()),"class=detail") + ); + } + + /** + * Implement the table content for Namespace Detail + * + * + */ + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private static final String[] headers = new String[0]; + private static final String CSP_ATT_COM = "@csp.att.com"; + private Slot name; + public Model(AuthzEnv env) { + name = env.slot(NAME+".name"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + final String nsName = trans.get(name, null); + if(nsName==null) { + return Cells.EMPTY; + } + 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.nssDF); + + if(fn.get(AuthGUI.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, rv, n.getAdmin(), NS_FIELD.ADMINS); + addField(trans, rv, n.getResponsible(), NS_FIELD.OWNERS); + + Future<Users> fu = client.read( + "/authn/creds/ns/"+nsName, + gui.usersDF + ); + List<String> creds = new ArrayList<String>(); + if(fu.get(AAFcli.timeout())) { + for (User u : fu.value.getUser()) { + StringBuilder sb = new StringBuilder(u.getId()); + switch(u.getType()) { + case 1: sb.append(" (U/Pass) "); break; + case 10: sb.append(" (Cert) "); break; + case 200: sb.append(" (x509) "); break; + default: + sb.append(" "); + } + sb.append(Chrono.niceDateStamp(u.getExpires())); + creds.add(sb.toString()); + } + } + addField(trans, rv, creds, NS_FIELD.CREDS); + + Future<Roles> fr = client.read( + "/authz/roles/ns/"+nsName, + gui.rolesDF + ); + List<String> roles = new ArrayList<String>(); + if(fr.get(AAFcli.timeout())) { + for (Role r : fr.value.getRole()) { + roles.add(r.getName()); + } + } + addField(trans, rv, roles, NS_FIELD.ROLES); + + + Future<Perms> fp = client.read( + "/authz/perms/ns/"+nsName, + gui.permsDF + ); + 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, rv, perms, NS_FIELD.PERMISSIONS); + } + String historyLink = NsHistory.HREF + + "?name=" + nsName; + rv.add(new AbsCell[] {new RefCell("See History",historyLink)}); + } 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, ArrayList<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('@'))):new TextCell(user)); + rv.add(new AbsCell[] { + label, + userCell + }); + } + break; + case ROLES: + for (int i=0; i< values.size(); i++) { + AbsCell label = (i==0?new TextCell(sentenceCase(field)+":"):AbsCell.Null); + rv.add(new AbsCell[] { + label, + new TextCell(values.get(i)) + }); + } + break; + case PERMISSIONS: + for (int i=0; i< values.size(); i++) { + AbsCell label = (i==0?new TextCell(sentenceCase(field)+":"):AbsCell.Null); + String perm = values.get(i); + String[] fields = perm.split("\\|"); + String grantLink = PermGrantForm.HREF + + "?type=" + fields[0].trim() + + "&instance=" + fields[1].trim() + + "&action=" + fields[2].trim(); + + rv.add(new AbsCell[] { + label, + new TextCell(perm), + new RefCell("Grant This Perm", grantLink) + }); + } + break; + } + + } + } + + private String sentenceCase(NS_FIELD field) { + String sField = field.toString(); + return sField.substring(0, 1).toUpperCase() + sField.substring(1).toLowerCase(); + } + + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/NsHistory.java b/authz-gui/src/main/java/com/att/authz/gui/pages/NsHistory.java new file mode 100644 index 00000000..c9a599f2 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/NsHistory.java @@ -0,0 +1,210 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.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 AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,NAME,HREF, FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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 + * + * + */ + private static class Model implements Table.Data<AuthGUI,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 AuthGUI gui, final AuthzTrans trans) { + final String oName = trans.get(name,null); + final String oDates = trans.get(dates,null); + + if(oName==null) { + return Cells.EMPTY; + } + + 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.historyDF); + if (fh.get(AuthGUI.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('@'))):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/authz-gui/src/main/java/com/att/authz/gui/pages/NsInfoAction.java b/authz-gui/src/main/java/com/att/authz/gui/pages/NsInfoAction.java new file mode 100644 index 00000000..79492d2b --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/NsInfoAction.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.text.ParseException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.inno.env.util.Chrono; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.CredRequest; + +public class NsInfoAction extends Page { + public NsInfoAction(final AuthGUI 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(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + cache.dynamic(hgen, new DynamicCode<HTMLGen,AuthGUI, AuthzTrans>() { + @Override + public void code(final AuthGUI gui, final AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + String id = trans.get(sID,null); + String currPass = trans.get(sCurrPass,null); + 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.credReqDF, + 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.credReqDF, + cred + ); + + if(fcr.get(5000)) { + // Do Remote Call + hgen.p("New Password has been added."); + fail = false; + } else { + gui.writeError(trans, fcr, hgen); + } + } 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/authz-gui/src/main/java/com/att/authz/gui/pages/NsInfoForm.java b/authz-gui/src/main/java/com/att/authz/gui/pages/NsInfoForm.java new file mode 100644 index 00000000..32b3c4c4 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/NsInfoForm.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import static com.att.xgen.html.HTMLGen.A; +import static com.att.xgen.html.HTMLGen.TABLE; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.List; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.Nss; +import aaf.v2_0.Nss.Ns; +import aaf.v2_0.Nss.Ns.Attrib; + +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 AuthGUI 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, AuthGUI, AuthzTrans>() { + @SuppressWarnings("unchecked") + @Override + public void code(final AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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.nssDF); + if(fn.get(AuthGUI.TIMEOUT)) { + for(Ns ns : fn.value.getNs()) { + info[0]=ns.getName(); + info[1]=ns.getDescription(); + for(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/authz-gui/src/main/java/com/att/authz/gui/pages/NssShow.java b/authz-gui/src/main/java/com/att/authz/gui/pages/NssShow.java new file mode 100644 index 00000000..0333d92c --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/NssShow.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; + +import aaf.v2_0.Nss; +import aaf.v2_0.Nss.Ns; + +public class NssShow extends Page { + public static final String HREF = "/gui/mynamespaces"; + + public NssShow(final AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, "MyNamespaces",HREF, NO_FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Namespaces I administer",gui.env.newTransNoAvg(),new Model("admin",gui.env), + "class=std", "style=display: inline-block; width: 45%; margin: 10px;"), + new Table<AuthGUI,AuthzTrans>("Namespaces I own",gui.env.newTransNoAvg(),new Model("responsible",gui.env), + "class=std", "style=display: inline-block; width: 45%; margin: 10px;")); + } + + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private String[] headers; + private String privilege = null; + public final Slot sNssByUser; + private boolean isAdmin; + + public Model(String privilege,AuthzEnv env) { + super(); + headers = new String[] {privilege}; + this.privilege = privilege; + isAdmin = "admin".equals(privilege); + sNssByUser = env.slot("NSS_SHOW_MODEL_DATA"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + 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.nssDF); + if(fp.get(AuthGUI.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); + } + 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 + +"?name="+n.getName()), + }; + rv.add(sa); + } + } + } + + return new Cells(rv,null); + } + } + + +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/PassChangeAction.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PassChangeAction.java new file mode 100644 index 00000000..eeb2b0ec --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PassChangeAction.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.text.ParseException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.inno.env.util.Chrono; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.CredRequest; + +public class PassChangeAction extends Page { + public PassChangeAction(final AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,"PassChange",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(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + cache.dynamic(hgen, new DynamicCode<HTMLGen,AuthGUI, AuthzTrans>() { + @Override + public void code(final AuthGUI gui, final AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + String id = trans.get(sID,null); + String currPass = trans.get(sCurrPass,null); + 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 { + boolean fail = true; + boolean go = false; + 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.credReqDF,cred); + + 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; + } + } finally { + tt.done(); + } + if(go) { + 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 = client.create( + "/authn/cred", + gui.credReqDF, + cred + ); + + if(fcr.get(5000)) { + // Do Remote Call + hgen.p("New Password has been added."); + fail = false; + } else { + gui.writeError(trans, fcr, hgen); + } + } finally { + tt.done(); + } + } + return fail; + } + + }); + } 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/authz-gui/src/main/java/com/att/authz/gui/pages/PassChangeForm.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PassChangeForm.java new file mode 100644 index 00000000..4172235a --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PassChangeForm.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import static com.att.xgen.html.HTMLGen.TABLE; + +import java.io.IOException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.inno.env.APIException; +import com.att.inno.env.Slot; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + +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"}; + + public PassChangeForm(final AuthGUI 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(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.leaf("p").text("You are requesting a new Mechanical Password in the AAF System. " + + "So that you can perform clean migrations, you will be able to use both this " + + "new password and the old one until their respective expiration dates.").end() + .leaf("p").text("Note: You must be a Namespace Admin where the MechID resides.").end() + .incr("form","method=post"); + Mark table = new Mark(TABLE); + hgen.incr(table); + cache.dynamic(hgen, new DynamicCode<HTMLGen, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { +// GregorianCalendar gc = new GregorianCalendar(); +// System.out.println(gc.toString()); + String incomingID= trans.get(sID, ""); + hgen + .input(fields[0],"ID*",true,"value="+incomingID) + .input(fields[1],"Current Password*",true,"type=password") + .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(); + } + }); + hgen.end(); + hgen.tagOnly("input", "type=submit", "value=Submit") + .end(); + + } + }); + } + +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/PendingRequestsShow.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PendingRequestsShow.java new file mode 100644 index 00000000..c0dd3f7f --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PendingRequestsShow.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.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 final String DATE_TIME_FORMAT = "yyyy-MM-dd"; + + public PendingRequestsShow(final AuthGUI 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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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<AuthGUI,AuthzTrans>("Pending Requests",gui.env.newTransNoAvg(),new Model(), "class=std") + ); + + + } + + /** + * Implement the Table Content for Requests by User + * + * + */ + private static class Model implements Table.Data<AuthGUI,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 AuthGUI gui, final AuthzTrans trans) { + DateFormat createdDF = new SimpleDateFormat(DATE_TIME_FORMAT); + 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.approvalsDF); + 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.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=" + a.getTicket()); + prevTicket = ticket; + } + + AbsCell approverCell = null; + if (approver.endsWith(CSP_ATT_COM)) { + approverCell = new RefCell(approver, WEBPHONE + approverShort); + } 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); + } + } finally { + tt.done(); + } + + + return null; + } + }); + } catch (Exception e) { + trans.error().log(e); + } + return new Cells(rv,null); + } + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/PermDetail.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PermDetail.java new file mode 100644 index 00000000..784642cd --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PermDetail.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; +import java.util.List; + +import com.att.aft.dme2.internal.jetty.http.HttpStatus; +import com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; + +import aaf.v2_0.Perm; +import aaf.v2_0.Perms; + +/** + * Detail Page for Permissions + * + */ +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 AuthGUI gui, Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, NAME, HREF, new String[] {"type","instance","action"}, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Permission Details",gui.env.newTransNoAvg(),new Model(gui.env()),"class=detail") + ); + } + + /** + * Implement the table content for Permissions Detail + * + * + */ + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private static final String[] headers = new String[0]; + private Slot type, instance, action; + public Model(AuthzEnv env) { + type = env.slot(NAME+".type"); + instance = env.slot(NAME+".instance"); + action = env.slot(NAME+".action"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + final String pType = trans.get(type, null); + final String pInstance = trans.get(instance, null); + final String pAction = trans.get(action, null); + if(pType==null || pInstance==null || pAction==null) { + return Cells.EMPTY; + } + 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.permsDF); + + if(fp.get(AuthGUI.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)}); + } 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/authz-gui/src/main/java/com/att/authz/gui/pages/PermGrantAction.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PermGrantAction.java new file mode 100644 index 00000000..a7aacc20 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PermGrantAction.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.html.HTMLGen; + +import aaf.v2_0.Pkey; +import aaf.v2_0.RolePermRequest; + +public class PermGrantAction extends Page { + + + public PermGrantAction(final AuthGUI 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(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + cache.dynamic(hgen, new DynamicCode<HTMLGen,AuthGUI, AuthzTrans>() { + @Override + public void code(final AuthGUI gui, final AuthzTrans trans,Cache<HTMLGen> cache, 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.rolePermReqDF, + 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); + } + } + 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/authz-gui/src/main/java/com/att/authz/gui/pages/PermGrantForm.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PermGrantForm.java new file mode 100644 index 00000000..bd3884f1 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PermGrantForm.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import static com.att.xgen.html.HTMLGen.TABLE; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; +import java.util.List; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.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 AuthGUI 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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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 AuthGUI gui, final AuthzTrans trans) { + 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.rolesDF); + 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); + } + } finally { + tt.done(); + } + return null; + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + + return myRoles; + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/PermHistory.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PermHistory.java new file mode 100644 index 00000000..0a204051 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PermHistory.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.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 AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,NAME,HREF, FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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 + * + * + */ + private static class Model implements Table.Data<AuthGUI,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 AuthGUI gui, final AuthzTrans trans) { + final String oName = trans.get(sType,null); + final String oDates = trans.get(sDates,null); + + if(oName==null) { + return Cells.EMPTY; + } + + 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.historyDF + ); + + + if (fh.get(AuthGUI.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('@'))):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/authz-gui/src/main/java/com/att/authz/gui/pages/PermsShow.java b/authz-gui/src/main/java/com/att/authz/gui/pages/PermsShow.java new file mode 100644 index 00000000..9af71ef7 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/PermsShow.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.TimeTaken; + +import aaf.v2_0.Perm; +import aaf.v2_0.Perms; + +/** + * Page content for My Permissions + * + * + */ +public class PermsShow extends Page { + public static final String HREF = "/gui/myperms"; + + public PermsShow(final AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, "MyPerms",HREF, NO_FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Permissions",gui.env.newTransNoAvg(),new Model(), "class=std")); + } + + /** + * Implement the Table Content for Permissions by User + * + * + */ + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private static final String[] headers = new String[] {"Type","Instance","Action"}; + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + 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.permsDF); + 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()), + new TextCell(p.getInstance()), + new TextCell(p.getAction()) + }; + rv.add(sa); + } + } else { + gui.writeError(trans, fp, null); + } + } finally { + ttld.done(); + } + } + return null; + } + }); + } catch (Exception e) { + trans.error().log(e); + } finally { + tt.done(); + } + return new Cells(rv,null); + } + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/RequestDetail.java b/authz-gui/src/main/java/com/att/authz/gui/pages/RequestDetail.java new file mode 100644 index 00000000..a2d06cdf --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/RequestDetail.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.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 AuthGUI gui, Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, NAME, HREF, FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Request Details",gui.env.newTransNoAvg(),new Model(gui.env()),"class=detail") + ); + } + + /** + * Implement the table content for Request Detail + * + * + */ + private static class Model implements Table.Data<AuthGUI,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 static final String[] headers = new String[0]; + private Slot sTicket; + public Model(AuthzEnv env) { + sTicket = env.slot(NAME+".ticket"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + 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.approvalsDF + ); + + if(fa.get(AuthGUI.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("@")),"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); + } 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/authz-gui/src/main/java/com/att/authz/gui/pages/RoleDetail.java b/authz-gui/src/main/java/com/att/authz/gui/pages/RoleDetail.java new file mode 100644 index 00000000..426928b8 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/RoleDetail.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; + +import com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; + +import aaf.v2_0.Pkey; +import aaf.v2_0.Role; +import aaf.v2_0.Roles; + +/** + * Detail Page for Permissions + * + * + */ +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 AuthGUI gui, Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, NAME, HREF, new String[] {"role"}, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Role Details",gui.env.newTransNoAvg(),new Model(gui.env()),"class=detail") + ); + } + + /** + * Implement the table content for Permissions Detail + * + * + */ + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private static final String[] headers = new String[0]; + private Slot role; + public Model(AuthzEnv env) { + role = env.slot(NAME+".role"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + final String pRole = trans.get(role, null); + Cells rv = Cells.EMPTY; + if(pRole!=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[]>(); + rv.add(new AbsCell[]{new TextCell("Role:"),new TextCell(pRole)}); + + TimeTaken tt = trans.start("AAF Role Details",Env.REMOTE); + try { + + Future<Roles> fr = client.read("/authz/roles/"+pRole,gui.rolesDF); + if(fr.get(AuthGUI.TIMEOUT)) { + tt.done(); + tt = trans.start("Load Data", Env.SUB); + Role role = fr.value.getRole().get(0); + String desc = (role.getDescription()!=null?role.getDescription():BLANK); + rv.add(new AbsCell[]{new TextCell("Description:"),new TextCell(desc)}); + boolean first=true; + for(Pkey r : role.getPerms()) { + if(first){ + first=false; + rv.add(new AbsCell[] { + new TextCell("Associated Permissions:"), + new TextCell(r.getType() + + " | " + r.getInstance() + + " | " + r.getAction() + ) + }); + } else { + rv.add(new AbsCell[] { + AbsCell.Null, + new TextCell(r.getType() + + " | " + r.getInstance() + + " | " + r.getAction() + ) + }); + } + } + String historyLink = RoleHistory.HREF + + "?role=" + pRole; + rv.add(new AbsCell[] {new RefCell("See History",historyLink)}); + } 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; + } + } +} +
\ No newline at end of file diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/RoleHistory.java b/authz-gui/src/main/java/com/att/authz/gui/pages/RoleHistory.java new file mode 100644 index 00000000..80f1bc51 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/RoleHistory.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.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 com.att.authz.env.AuthzEnv; +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.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 AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,NAME,HREF, FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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 + * + * + */ + private static class Model implements Table.Data<AuthGUI,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 AuthGUI gui, final AuthzTrans trans) { + 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.historyDF); + if (fh.get(AuthGUI.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('@'))):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/authz-gui/src/main/java/com/att/authz/gui/pages/RolesShow.java b/authz-gui/src/main/java/com/att/authz/gui/pages/RolesShow.java new file mode 100644 index 00000000..e1d93eeb --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/RolesShow.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.Page; +import com.att.authz.gui.Table; +import com.att.authz.gui.Table.Cells; +import com.att.authz.gui.table.AbsCell; +import com.att.authz.gui.table.RefCell; +import com.att.authz.gui.table.TextCell; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.TimeTaken; +import com.att.inno.env.util.Chrono; + +import aaf.v2_0.UserRole; +import aaf.v2_0.UserRoles; + + +/** + * Page content for My Roles + * + * + */ +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 AuthGUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env, "MyRoles",HREF, NO_FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AuthGUI,AuthzTrans>("Roles",gui.env.newTransNoAvg(),new Model(), "class=std")); + } + + /** + * Implement the Table Content for Permissions by User + * + * + */ + private static class Model implements Table.Data<AuthGUI,AuthzTrans> { + private static final String[] headers = new String[] {"Role","Expires","Remediation","Actions"}; + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthGUI gui, final AuthzTrans trans) { + 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.userrolesDF); + 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(), + new String[]{"class=expired"}), + new RefCell("Remove", + UserRoleRemove.HREF + "?user="+trans.user()+"&role="+u.getRole(), + new String[]{"class=expired"}) + + }; + rv.add(sa); + } else { + AbsCell[] sa = new AbsCell[] { + new RefCell(u.getRole(), + RoleDetail.HREF+"?role="+u.getRole()), + new TextCell(expiresDF.format(u.getExpires().toGregorianCalendar().getTime())), + AbsCell.Null, + new RefCell("Remove", + UserRoleRemove.HREF + "?user="+trans.user()+"&role="+u.getRole()) + }; + rv.add(sa); + } + } + } + + } finally { + tt.done(); + } + return new Cells(rv,null); + } + }); + } catch (Exception e) { + trans.error().log(e); + } + return rv; + } + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/UserRoleExtend.java b/authz-gui/src/main/java/com/att/authz/gui/pages/UserRoleExtend.java new file mode 100644 index 00000000..1dc057da --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/UserRoleExtend.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.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 AuthGUI 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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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); + } + } + return null; + } + }); + } catch (Exception e) { + trans.error().log(e); + e.printStackTrace(); + } finally { + tt.done(); + } + + + } + }); + } + + }); + } +} + diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/UserRoleRemove.java b/authz-gui/src/main/java/com/att/authz/gui/pages/UserRoleRemove.java new file mode 100644 index 00000000..0140a7f6 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/UserRoleRemove.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; +import java.net.ConnectException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.cadi.CadiException; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; +import com.att.inno.env.Env; +import com.att.inno.env.Slot; +import com.att.inno.env.TimeTaken; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.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 AuthGUI 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, AuthGUI, AuthzTrans>() { + @Override + public void code(AuthGUI gui, AuthzTrans trans, Cache<HTMLGen> cache, 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); + } + } + return null; + } + }); + } catch (Exception e) { + e.printStackTrace(); + } finally { + tt.done(); + } + } + }); + } + + }); + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/pages/WebCommand.java b/authz-gui/src/main/java/com/att/authz/gui/pages/WebCommand.java new file mode 100644 index 00000000..a13beb58 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/pages/WebCommand.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.pages; + +import java.io.IOException; + +import com.att.authz.env.AuthzTrans; +import com.att.authz.gui.AuthGUI; +import com.att.authz.gui.BreadCrumbs; +import com.att.authz.gui.NamedCode; +import com.att.authz.gui.Page; +import com.att.inno.env.APIException; +import com.att.xgen.Cache; +import com.att.xgen.DynamicCode; +import com.att.xgen.Mark; +import com.att.xgen.html.HTMLGen; + +public class WebCommand extends Page { + public static final String HREF = "/gui/cui"; + + public WebCommand(final AuthGUI 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(Cache<HTMLGen> cache, HTMLGen hgen) throws APIException, IOException { + hgen.leaf("p","id=help_msg") + .text("Questions about this page? ") + .leaf("a", "href=http://wiki.web.att.com/display/aaf/Web+CUI+Usage", "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=../../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,AuthGUI,AuthzTrans>() { + @Override + public void code(AuthGUI 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=../../theme/AAFdownload.png", "onclick=saveToFile();", + "alt=Save log to file", "title=Save log to file"); + } +// xgen.img("src=../../theme/AAFemail.png", "onclick=emailLog();", +// "alt=Email log to me", "title=Email log to me"); + xgen.img("src=../../theme/AAF_font_size.png", "onclick=handleDivHiding('text_slider',this);", + "id=fontsize_img", "alt=Change text size", "title=Change text size"); + xgen.img("src=../../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=../../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/authz-gui/src/main/java/com/att/authz/gui/table/AbsCell.java b/authz-gui/src/main/java/com/att/authz/gui/table/AbsCell.java new file mode 100644 index 00000000..eb91c22a --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/table/AbsCell.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.table; + +import com.att.xgen.html.HTMLGen; + +public abstract class AbsCell { + private static final String[] NONE = new String[0]; + protected static final String[] CENTER = new String[]{"class=center"}; + + /** + * 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/authz-gui/src/main/java/com/att/authz/gui/table/ButtonCell.java b/authz-gui/src/main/java/com/att/authz/gui/table/ButtonCell.java new file mode 100644 index 00000000..4c270cfc --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/table/ButtonCell.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.table; + +import com.att.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/authz-gui/src/main/java/com/att/authz/gui/table/RadioCell.java b/authz-gui/src/main/java/com/att/authz/gui/table/RadioCell.java new file mode 100644 index 00000000..b4fa6440 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/table/RadioCell.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.table; + +import com.att.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.incr("input",true,attrs).end(); + } + + @Override + public String[] attrs() { + return AbsCell.CENTER; + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/table/RefCell.java b/authz-gui/src/main/java/com/att/authz/gui/table/RefCell.java new file mode 100644 index 00000000..49719837 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/table/RefCell.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.table; + +import static com.att.xgen.html.HTMLGen.A; + +import com.att.xgen.html.HTMLGen; + +/** + * Write a Reference Link into a Cell + * + */ +public class RefCell extends AbsCell { + public final String name; + public final String href; + private String[] attrs; + + public RefCell(String name, String href, String... attributes) { + attrs = new String[attributes.length]; + System.arraycopy(attributes, 0, attrs, 0, attributes.length); + this.name = name; + this.href = href; + } + + @Override + public void write(HTMLGen hgen) { + hgen.leaf(A,"href="+href).text(name); + } + + @Override + public String[] attrs() { + return attrs; + } +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/table/TextAndRefCell.java b/authz-gui/src/main/java/com/att/authz/gui/table/TextAndRefCell.java new file mode 100644 index 00000000..1c25361b --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/table/TextAndRefCell.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.table; + +import static com.att.xgen.html.HTMLGen.A; + +import com.att.xgen.html.HTMLGen; + +public class TextAndRefCell extends RefCell { + + private String text; + + public TextAndRefCell(String text, String name, String href, String[] attributes) { + super(name, href, attributes); + this.text = text; + } + + @Override + public void write(HTMLGen hgen) { + hgen.text(text); + hgen.leaf(A,"href="+href).text(name); + } + +} diff --git a/authz-gui/src/main/java/com/att/authz/gui/table/TextCell.java b/authz-gui/src/main/java/com/att/authz/gui/table/TextCell.java new file mode 100644 index 00000000..d0987920 --- /dev/null +++ b/authz-gui/src/main/java/com/att/authz/gui/table/TextCell.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + *******************************************************************************/ +package com.att.authz.gui.table; + +import com.att.xgen.html.HTMLGen; + +/** + * Write Simple Text into a Cell + * + */ +public class TextCell extends AbsCell { + public final String name; + private String[] attrs; + + public TextCell(String name, String... attributes) { + attrs = new String[attributes.length]; + System.arraycopy(attributes, 0, attrs, 0, attributes.length); + this.name = name; + } + + @Override + public void write(HTMLGen hgen) { + hgen.text(name); + } + + @Override + public String[] attrs() { + return attrs; + } +} |