X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=auth%2Fauth-service%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Faaf%2Fauth%2Fservice%2FAuthzCassServiceImpl.java;h=2431e0ebb1d7e6e6d66866a46d5e340ffe7f0dc1;hb=1296352d8eafee57f982a4342ad79ada4aa56d28;hp=9a6ef7e322e05e346b8c48e2dade104e34fc223a;hpb=0c883163f5d2da8573e56fab3ddb62a1ca5b889e;p=aaf%2Fauthz.git diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java index 9a6ef7e3..2431e0eb 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,6 +42,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.UUID; +import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; @@ -98,8 +99,8 @@ import org.onap.aaf.misc.env.util.Split; import aaf.v2_0.CredRequest; /** - * AuthzCassServiceImpl implements AuthzCassService for - * + * AuthzCassServiceImpl implements AuthzCassService for + * * @author Jonathan * * @param @@ -115,12 +116,12 @@ import aaf.v2_0.CredRequest; */ public class AuthzCassServiceImpl implements AuthzService { - + private static final String TWO_SPACE = " "; - private Mapper mapper; + private Mapper mapper; @Override public Mapper mapper() {return mapper;} - + private static final String ASTERIX = "*"; private static final String CACHE = "cache"; private static final String ROOT_NS = Define.ROOT_NS(); @@ -128,28 +129,28 @@ public class AuthzCassServiceImpl mapper,Question question) { this.ques = question; func = new Function(trans, question); this.mapper = mapper; - + } /*********************************** - * NAMESPACE + * NAMESPACE ***********************************/ /** * createNS - * @throws DAOException + * @throws DAOException * @see org.onap.aaf.auth.service.AuthzService#createNS(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.String, java.lang.String) */ - @ApiDoc( - method = POST, + @ApiDoc( + method = POST, path = "/authz/ns", params = {}, expectedCode = 201, - errorCodes = { 403,404,406,409 }, + errorCodes = { 403,404,406,409 }, text = { "Namespace consists of: ", "
  • name - What you want to call this Namespace
  • ", "
  • responsible(s) - Person(s) who receive Notifications and approves Requests ", @@ -167,7 +168,7 @@ public class AuthzCassServiceImpl createNS(final AuthzTrans trans, REQUEST from, NsType type) { final Result rnamespace = mapper.ns(trans, from); final ServiceValidator v = new ServiceValidator(); - if (v.ns(rnamespace).err()) { + if (v.ns(rnamespace).err()) { return Result.err(Status.ERR_BadData,v.errs()); } final Namespace namespace = rnamespace.value; @@ -175,13 +176,13 @@ public class AuthzCassServiceImpl fd = mapper.future(trans, NsDAO.TABLE,from,namespace,true, + + Result fd = mapper.future(trans, NsDAO.TABLE,from,namespace,true, new Mapper.Memo() { @Override public String get() { @@ -203,7 +204,7 @@ public class AuthzCassServiceImpl rfc = func.createFuture(trans, fd.value, namespace.name, trans.user(),parentNs.value, FUTURE_OP.C); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "NS [%s] is saved for future processing",namespace.name); - } else { + } else { return Result.err(rfc); } case Status.ACC_Now: @@ -212,16 +213,16 @@ public class AuthzCassServiceImpl > rlnd = ques.nsDAO().read(trans, ns); if (rlnd.isOK()) { if (rlnd.isEmpty()) { @@ -493,10 +494,10 @@ public class AuthzCassServiceImpl rnd = ques.mayUser(trans, trans.user(), rlnd.value.get(0), Access.read); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } - - + + Namespace namespace = new Namespace(rnd.value); Result> rd = func.getOwners(trans, namespace.name, includeExpired); if (rd.isOK()) { @@ -506,7 +507,7 @@ public class AuthzCassServiceImpl > rn = loadNamepace(trans, user, ".admin", full); if (rn.notOK()) { return Result.err(rn); } if (rn.isEmpty()) { - return Result.err(Status.ERR_NotFound, "[%s] is not an admin for any namespaces",user); + return Result.err(Status.ERR_NotFound, "[%s] is not an admin for any namespaces",user); } NSS nss = mapper.newInstance(API.NSS); // Note: "loadNamespace" already validates view of Namespace @@ -544,13 +545,13 @@ public class AuthzCassServiceImpl > rn = loadNamepace(trans, user, null, full); if (rn.notOK()) { return Result.err(rn); } if (rn.isEmpty()) { - return Result.err(Status.ERR_NotFound, "[%s] is not an admin or owner for any namespaces",user); + return Result.err(Status.ERR_NotFound, "[%s] is not an admin or owner for any namespaces",user); } NSS nss = mapper.newInstance(API.NSS); // Note: "loadNamespace" already validates view of Namespace @@ -594,7 +595,7 @@ public class AuthzCassServiceImpl rnd = ques.deriveNs(trans, parent); if (rnd.notOK()) { return Result.err(rnd); } rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } Set lm = new HashSet<>(); @@ -700,7 +701,7 @@ public class AuthzCassServiceImpl > rlnd = ques.nsDAO().read(trans, namespace.name); - + if (rlnd.notOKorIsEmpty()) { return Result.err(Status.ERR_NotFound, "Namespace [%s] does not exist",namespace.name); } - + if (ques.mayUser(trans, trans.user(), rlnd.value.get(0), Access.write).notOK()) { return Result.err(Status.ERR_Denied, "You do not have approval to change %s",namespace.name); } @@ -754,18 +755,18 @@ public class AuthzCassServiceImpl
  • type - a Namespace qualified identifier specifying what kind of resource " + "is being protected
  • ", @@ -805,7 +806,7 @@ public class AuthzCassServiceImpl createPerm(final AuthzTrans trans,REQUEST rreq) { + public Result createPerm(final AuthzTrans trans,REQUEST rreq) { final Result newPd = mapper.perm(trans, rreq); final ServiceValidator v = new ServiceValidator(); @@ -815,129 +816,129 @@ public class AuthzCassServiceImpl 0) { - PermDAO.Data pdd = newPd.value; - if(trans.user().equals(newPd.value.ns)) { - CachedPermDAO permDAO = ques.permDAO(); - Result> rlpdd = permDAO.read(trans, pdd); - if(rlpdd.notOK()) { - return Result.err(rlpdd); - } - if(!rlpdd.isEmpty()) { - return Result.err(Result.ERR_ConflictAlreadyExists,"Permission already exists"); - } - - RoleDAO.Data rdd = new RoleDAO.Data(); - rdd.ns = pdd.ns; - rdd.name = "user"; - - pdd.roles(true).add(rdd.fullName()); - Result rpdd = permDAO.create(trans, pdd); - if(rpdd.notOK()) { - return Result.err(rpdd); - } - - CachedRoleDAO roleDAO = ques.roleDAO(); - Result> rlrdd = roleDAO.read(trans, rdd); - if(rlrdd.notOK()) { - return Result.err(rlrdd); - } else { - if(!rlrdd.isEmpty()) { - rdd = rlrdd.value.get(0); - } - } - - String eperm = pdd.encode(); - rdd.perms(true).add(eperm); - Result rv = roleDAO.update(trans, rdd); - if(rv.notOK()) { - return rv; - } - - CachedUserRoleDAO urDAO = ques.userRoleDAO(); - UserRoleDAO.Data urdd = new UserRoleDAO.Data(); - urdd.user = trans.user(); - urdd.ns = rdd.ns; - urdd.rname = rdd.name; - urdd.role = rdd.fullName(); - Result> rlurdd = urDAO.read(trans, urdd); - if(rlurdd.notOK()) { - return Result.err(rlrdd); - } else if(rlurdd.isEmpty()) { - GregorianCalendar gc = trans.org().expiration(null, Expiration.UserInRole); - if(gc==null) { - return Result.err(Result.ERR_Policy,"Organzation does not grant Expiration for UserRole"); - } else { - urdd.expires = gc.getTime(); - } - Result rurdd = urDAO.create(trans, urdd); - return Result.err(rurdd); - } - return rv; - } else { - return Result.err(Result.ERR_Security,"Only the User can create User Permissions"); - } + PermDAO.Data pdd = newPd.value; + if(trans.user().equals(newPd.value.ns)) { + CachedPermDAO permDAO = ques.permDAO(); + Result> rlpdd = permDAO.read(trans, pdd); + if(rlpdd.notOK()) { + return Result.err(rlpdd); + } + if(!rlpdd.isEmpty()) { + return Result.err(Result.ERR_ConflictAlreadyExists,"Permission already exists"); + } + + RoleDAO.Data rdd = new RoleDAO.Data(); + rdd.ns = pdd.ns; + rdd.name = "user"; + + pdd.roles(true).add(rdd.fullName()); + Result rpdd = permDAO.create(trans, pdd); + if(rpdd.notOK()) { + return Result.err(rpdd); + } + + CachedRoleDAO roleDAO = ques.roleDAO(); + Result> rlrdd = roleDAO.read(trans, rdd); + if(rlrdd.notOK()) { + return Result.err(rlrdd); + } else { + if(!rlrdd.isEmpty()) { + rdd = rlrdd.value.get(0); + } + } + + String eperm = pdd.encode(); + rdd.perms(true).add(eperm); + Result rv = roleDAO.update(trans, rdd); + if(rv.notOK()) { + return rv; + } + + CachedUserRoleDAO urDAO = ques.userRoleDAO(); + UserRoleDAO.Data urdd = new UserRoleDAO.Data(); + urdd.user = trans.user(); + urdd.ns = rdd.ns; + urdd.rname = rdd.name; + urdd.role = rdd.fullName(); + Result> rlurdd = urDAO.read(trans, urdd); + if(rlurdd.notOK()) { + return Result.err(rlrdd); + } else if(rlurdd.isEmpty()) { + GregorianCalendar gc = trans.org().expiration(null, Expiration.UserInRole); + if(gc==null) { + return Result.err(Result.ERR_Policy,"Organzation does not grant Expiration for UserRole"); + } else { + urdd.expires = gc.getTime(); + } + Result rurdd = urDAO.create(trans, urdd); + return Result.err(rurdd); + } + return rv; + } else { + return Result.err(Result.ERR_Security,"Only the User can create User Permissions"); + } } else { - // Does Perm Type exist as a Namespace? - if(newPd.value.type.isEmpty() || ques.nsDAO().read(trans, newPd.value.fullType()).isOKhasData()) { - return Result.err(Status.ERR_ConflictAlreadyExists, - "Permission Type exists as a Namespace"); - } - - Result fd = mapper.future(trans, PermDAO.TABLE, rreq, newPd.value,false, - new Mapper.Memo() { - @Override - public String get() { - return "Create Permission [" + - newPd.value.fullType() + '|' + - newPd.value.instance + '|' + - newPd.value.action + ']'; - } - }, - new MayChange() { - private Result nsd; - @Override - public Result mayChange() { - if (nsd==null) { - nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write); - } - return nsd; - } - }); - - Result> nsr = ques.nsDAO().read(trans, newPd.value.ns); - if (nsr.notOKorIsEmpty()) { - return Result.err(nsr); - } - switch(fd.status) { - case OK: - Result rfc = func.createFuture(trans,fd.value, - newPd.value.fullType() + '|' + newPd.value.instance + '|' + newPd.value.action, - trans.user(), - nsr.value.get(0), - FUTURE_OP.C); - if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", - newPd.value.ns, - newPd.value.type, - newPd.value.instance, - newPd.value.action); - } else { - return Result.err(rfc); - } - case Status.ACC_Now: - return func.createPerm(trans, newPd.value, true); - default: - return Result.err(fd); - } + // Does Perm Type exist as a Namespace? + if(newPd.value.type.isEmpty() || ques.nsDAO().read(trans, newPd.value.fullType()).isOKhasData()) { + return Result.err(Status.ERR_ConflictAlreadyExists, + "Permission Type exists as a Namespace"); + } + + Result fd = mapper.future(trans, PermDAO.TABLE, rreq, newPd.value,false, + new Mapper.Memo() { + @Override + public String get() { + return "Create Permission [" + + newPd.value.fullType() + '|' + + newPd.value.instance + '|' + + newPd.value.action + ']'; + } + }, + new MayChange() { + private Result nsd; + @Override + public Result mayChange() { + if (nsd==null) { + nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write); + } + return nsd; + } + }); + + Result> nsr = ques.nsDAO().read(trans, newPd.value.ns); + if (nsr.notOKorIsEmpty()) { + return Result.err(nsr); + } + switch(fd.status) { + case OK: + Result rfc = func.createFuture(trans,fd.value, + newPd.value.fullType() + '|' + newPd.value.instance + '|' + newPd.value.action, + trans.user(), + nsr.value.get(0), + FUTURE_OP.C); + if (rfc.isOK()) { + return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", + newPd.value.ns, + newPd.value.type, + newPd.value.instance, + newPd.value.action); + } else { + return Result.err(rfc); + } + case Status.ACC_Now: + return func.createPerm(trans, newPd.value, true); + default: + return Result.err(fd); + } } } - @ApiDoc( - method = GET, + @ApiDoc( + method = GET, path = "/authz/perms/:type", params = {"type|string|true"}, expectedCode = 200, - errorCodes = { 404,406 }, + errorCodes = { 404,406 }, text = { "List All Permissions that match the :type element of the key" } ) @Override @@ -955,7 +956,7 @@ public class AuthzCassServiceImpl r; // if ((r = ques.mayUserViewPerm(trans, trans.user(), permType)).notOK())return Result.err(r); - + PERMS perms = mapper.newInstance(API.PERMS); if (!rlpd.isEmpty()) { // Note: Mapper will restrict what can be viewed @@ -963,15 +964,15 @@ public class AuthzCassServiceImpl > rlpd = ques.getPermsByName(trans, type, instance, action); if (rlpd.notOK()) { return Result.err(rlpd); @@ -996,12 +997,12 @@ public class AuthzCassServiceImpl 'user' must be expressed as full identity (ex: id@full.domain.com)

    "} ) @@ -1017,25 +1018,25 @@ public class AuthzCassServiceImpl 'user' must be expressed as full identity (ex: id@full.domain.com)

    ", "

    'scope' must be expressed as NSs separated by ':'

    " @@ -1052,26 +1053,26 @@ public class AuthzCassServiceImpl 'user' must be expressed as full identity (ex: id@full.domain.com)

    ", "", @@ -1099,15 +1100,15 @@ public class AuthzCassServiceImpl > rlpd = pl.getPerms(trans.requested(force)); if (rlpd.notOK()) { return Result.err(rlpd); } - - /*//TODO + + /*//TODO 1) See if allowed to query 2) See if User is allowed */ @@ -1149,25 +1150,25 @@ public class AuthzCassServiceImpl > rlpd = ques.permDAO().readNS(trans, ns); if (rlpd.notOK()) { return Result.err(rlpd); @@ -1234,15 +1235,15 @@ public class AuthzCassServiceImpl nss = ques.deriveNsSplit(trans, origType); - Result> origRlpd = ques.permDAO().read(trans, nss.value.ns, nss.value.name, origInstance, origAction); - + Result> origRlpd = ques.permDAO().read(trans, nss.value.ns, nss.value.name, origInstance, origAction); + if (origRlpd.notOKorIsEmpty()) { - return Result.err(Status.ERR_PermissionNotFound, + return Result.err(Status.ERR_PermissionNotFound, "Permission [%s|%s|%s] does not exist", origType,origInstance,origAction); } - + PermDAO.Data origPd = origRlpd.value.get(0); if (!origPd.ns.equals(newPd.value.ns)) { return Result.err(Status.ERR_Denied, "Cannot change namespace with rename command. " + " must start with [" + origPd.ns + "]"); } - - if ( origPd.type.equals(newPd.value.type) && - origPd.action.equals(newPd.value.action) && + + if ( origPd.type.equals(newPd.value.type) && + origPd.action.equals(newPd.value.action) && origPd.instance.equals(newPd.value.instance) ) { return Result.err(Status.ERR_ConflictAlreadyExists, "New Permission must be different than original permission"); } - + Set origRoles = origPd.roles(false); if (!origRoles.isEmpty()) { Set roles = newPd.value.roles(true); for (String role : origPd.roles) { - roles.add(role); + roles.add(role); } - } - + } + newPd.value.description = origPd.description; - + Result rv = null; - + rv = func.createPerm(trans, newPd.value, false); if (rv.isOK()) { rv = func.deletePerm(trans, origPd, true, false); } return rv; } - - @ApiDoc( - method = PUT, + + @ApiDoc( + method = PUT, path = "/authz/perm", params = {}, expectedCode = 200, - errorCodes = { 404,406 }, + errorCodes = { 404,406 }, text = { "Add Description Data to Perm" } ) @Override @@ -1343,7 +1344,7 @@ public class AuthzCassServiceImpl > rcurr = ques.permDAO().read(trans, - updt.value.ns, - updt.value.type, - updt.value.instance, + Result> rcurr = ques.permDAO().read(trans, + updt.value.ns, + updt.value.type, + updt.value.instance, updt.value.action); - + if (rcurr.notOKorIsEmpty()) { - return Result.err(Status.ERR_PermissionNotFound, + return Result.err(Status.ERR_PermissionNotFound, "Permission [%s.%s|%s|%s] does not exist", updt.value.ns,updt.value.type,updt.value.instance,updt.value.action); } - + // Create a set of Update Roles, which are in Internal Format Set updtRoles = new HashSet<>(); Result nss; @@ -1396,11 +1397,11 @@ public class AuthzCassServiceImpl rv = null; - + for (PermDAO.Data curr : rcurr.value) { Set currRoles = curr.roles(false); - // must add roles to this perm, and add this perm to each role - // in the update, but not in the current + // must add roles to this perm, and add this perm to each role + // in the update, but not in the current for (String role : updtRoles) { if (!currRoles.contains(role)) { Result key = RoleDAO.Data.decode(trans, ques, role); @@ -1436,17 +1437,17 @@ public class AuthzCassServiceImpl fd = mapper.future(trans,PermDAO.TABLE,from,perm,false, new Mapper.Memo() { @Override @@ -1486,36 +1487,36 @@ public class AuthzCassServiceImpl > nsr = ques.nsDAO().read(trans, perm.ns); if (nsr.notOKorIsEmpty()) { return Result.err(nsr); } - - Result rfc = func.createFuture(trans, fd.value, + + Result rfc = func.createFuture(trans, fd.value, perm.encode(), trans.user(),nsr.value.get(0),FUTURE_OP.D); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "Perm Deletion [%s] is saved for future processing",perm.encode()); - } else { + } else { return Result.err(rfc); } case Status.ACC_Now: return func.deletePerm(trans,perm,trans.requested(force), false); default: return Result.err(fd); - } - } - - @ApiDoc( + } + } + + @ApiDoc( method = DELETE, path = "/authz/perm/:name/:type/:action", params = {"type|string|true", "instance|string|true", "action|string|true"}, expectedCode = 200, - errorCodes = { 404,406 }, + errorCodes = { 404,406 }, text = { "Delete the Permission referenced by :type :instance :action", "You cannot normally delete a permission which is still granted to roles,", "however the \"force\" property allows you to do just that. To do this: Add", @@ -1531,7 +1532,7 @@ public class AuthzCassServiceImpl pd = ques.permFrom(trans, type, instance, action); if (pd.isOK()) { return func.deletePerm(trans, pd.value, trans.requested(force), false); @@ -1541,7 +1542,7 @@ public class AuthzCassServiceImpl > nsr = ques.nsDAO().read(trans, rd.value.ns); if (nsr.notOKorIsEmpty()) { return Result.err(nsr); @@ -1608,13 +1609,13 @@ public class AuthzCassServiceImpl rfc = func.createFuture(trans, fd.value, + Result rfc = func.createFuture(trans, fd.value, role.encode(), trans.user(),nsr.value.get(0),FUTURE_OP.C); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "Role [%s.%s] is saved for future processing", rd.value.ns, rd.value.name); - } else { + } else { return Result.err(rfc); } case Status.ACC_Now: @@ -1635,7 +1636,7 @@ public class AuthzCassServiceImpl rrdd = RoleDAO.Data.decode(trans, ques, role); if (rrdd.isOKhasData()) { @@ -1659,7 +1660,7 @@ public class AuthzCassServiceImpl > rlrd = ques.getRolesByName(trans, query<0?role:role.substring(0, query)); @@ -1721,7 +1722,7 @@ public class AuthzCassServiceImpl rnsd = ques.deriveNs(trans, ns); + Result rnsd = ques.deriveNs(trans, ns); if (rnsd.notOK()) { - return Result.err(rnsd); + return Result.err(rnsd); } rnsd = ques.mayUser(trans, trans.user(), rnsd.value, Access.read); if (rnsd.notOK()) { - return Result.err(rnsd); + return Result.err(rnsd); } TimeTaken tt = trans.start("MAP Roles by NS to Roles", Env.SUB); @@ -1772,7 +1773,7 @@ public class AuthzCassServiceImpl > pdlr = ques.permDAO().read(trans, pdd); if (pdlr.isOK())for (PermDAO.Data pd : pdlr.value) { Result> rlrd; @@ -1909,7 +1910,7 @@ public class AuthzCassServiceImpl
  • type - a Namespace qualified identifier specifying what kind of resource " + "is being protected
  • ", "
  • instance - a key, possibly multi-dimensional, that identifies a specific " @@ -1941,7 +1942,7 @@ public class AuthzCassServiceImpl > rlpd = ques.permDAO().read(trans, rpd.value.ns, + Result> rlpd = ques.permDAO().read(trans, rpd.value.ns, rpd.value.type, rpd.value.instance, rpd.value.action); PermDAO.Data createPerm = null; // if not null, create first if (rlpd.notOKorIsEmpty()) { // Permission doesn't exist @@ -1965,7 +1966,7 @@ public class AuthzCassServiceImpl fd = mapper.future(trans, PermDAO.TABLE, rreq, rpd.value,true, // Allow grants to create Approvals new Mapper.Memo() { @Override @@ -1994,7 +1995,7 @@ public class AuthzCassServiceImpl rfc = func.createFuture(trans,fd.value, - rpd.value.fullPerm(), - trans.user(), - nsr.value.get(0), - FUTURE_OP.G); - if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", - rpd.value.ns, - rpd.value.type, - rpd.value.instance, - rpd.value.action); - } else { - return Result.err(rfc); - } - case Status.ACC_Now: - Result rv = null; - if (createPerm!=null) {// has been validated for creating - rv = func.createPerm(trans, createPerm, false); - } - if (rv==null || rv.isOK()) { - rv = func.addPermToRole(trans, rrd.value, rpd.value, false); - } - return rv; - default: - return Result.err(fd); - } - + case OK: + Result rfc = func.createFuture(trans,fd.value, + rpd.value.fullPerm(), + trans.user(), + nsr.value.get(0), + FUTURE_OP.G); + if (rfc.isOK()) { + return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", + rpd.value.ns, + rpd.value.type, + rpd.value.instance, + rpd.value.action); + } else { + return Result.err(rfc); + } + case Status.ACC_Now: + Result rv = null; + if (createPerm!=null) {// has been validated for creating + rv = func.createPerm(trans, createPerm, false); + } + if (rv==null || rv.isOK()) { + rv = func.addPermToRole(trans, rrd.value, rpd.value, false); + } + return rv; + default: + return Result.err(fd); + } + } /** @@ -2070,17 +2071,17 @@ public class AuthzCassServiceImpl delPermFromRole(final AuthzTrans trans, PermDAO.Data pdd, RoleDAO.Data rdd, REQUEST rreq) { - Result> rlpd = ques.permDAO().read(trans, pdd.ns, pdd.type, + + private Result delPermFromRole(final AuthzTrans trans, PermDAO.Data pdd, RoleDAO.Data rdd, REQUEST rreq) { + Result> rlpd = ques.permDAO().read(trans, pdd.ns, pdd.type, pdd.instance, pdd.action); - + if (rlpd.notOKorIsEmpty()) { - return Result.err(Status.ERR_PermissionNotFound, + return Result.err(Status.ERR_PermissionNotFound, "Permission [%s.%s|%s|%s] does not exist", pdd.ns,pdd.type,pdd.instance,pdd.action); } - + Result fd = mapper.future(trans, PermDAO.TABLE, rreq, pdd,true, // allow ungrants requests new Mapper.Memo() { @Override @@ -2105,7 +2106,7 @@ public class AuthzCassServiceImpl rfc = func.createFuture(trans,fd.value, + Result rfc = func.createFuture(trans,fd.value, pdd.fullPerm(), trans.user(), nsr.value.get(0), @@ -2126,7 +2127,7 @@ public class AuthzCassServiceImpl rrns = ques.deriveNs(trans, role); if (rrns.notOKorIsEmpty()) { return Result.err(rrns); } - + final Result> rrd = ques.roleDAO().read(trans, rrns.value.parent, rrns.value.name); if (rrd.notOKorIsEmpty()) { return Result.err(rrd); } - + final Result> rpd = ques.permDAO().read(trans, rpns.value.parent, rpns.value.name, instance, action); if (rpd.notOKorIsEmpty()) { return Result.err(rpd); } - + return delPermFromRole(trans,rpd.value.get(0), rrd.value.get(0), mapper.ungrantRequest(trans, role, type, instance, action)); } - + @ApiDoc( method = DELETE, path = "/authz/role/:role", @@ -2190,7 +2191,7 @@ public class AuthzCassServiceImpl rrdd = RoleDAO.Data.decode(trans,ques,role); if (rrdd.isOKhasData()) { final ServiceValidator v = new ServiceValidator(); - if (v.nullOrBlank(rrdd.value).err()) { + if (v.nullOrBlank(rrdd.value).err()) { return Result.err(Status.ERR_BadData,v.errs()); } return func.deleteRole(trans, rrdd.value, false, false); @@ -2240,21 +2241,21 @@ public class AuthzCassServiceImpl > nsr = ques.nsDAO().read(trans, rd.value.ns); if (nsr.notOKorIsEmpty()) { return Result.err(nsr); } - - Result rfc = func.createFuture(trans, fd.value, + + Result rfc = func.createFuture(trans, fd.value, role.encode(), trans.user(),nsr.value.get(0),FUTURE_OP.D); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "Role Deletion [%s.%s] is saved for future processing", rd.value.ns, rd.value.name); - } else { + } else { return Result.err(rfc); } case Status.ACC_Now: @@ -2266,14 +2267,14 @@ public class AuthzCassServiceImpl nsd; private AuthzTrans trans; private CredDAO.Data cred; private Executor exec; - + public MayCreateCred(AuthzTrans trans, CredDAO.Data cred, Executor exec) { this.trans = trans; this.cred = cred; @@ -2290,7 +2291,7 @@ public class AuthzCassServiceImpl rmc = ques.mayUser(trans, trans.user(), nsd.value, Access.write); if (rmc.isOKhasData()) { @@ -2309,12 +2310,12 @@ public class AuthzCassServiceImpl nsd; + private static final String RESET = "reset"; + private static final String DELETE = "delete"; + private Result nsd; private AuthzTrans trans; private CredDAO.Data cred; - private String action; + private String action; public MayChangeCred(AuthzTrans trans, CredDAO.Data cred, String action) { this.trans = trans; this.cred = cred; @@ -2329,48 +2330,48 @@ public class AuthzCassServiceImpl
  • id - the ID to create within AAF. The domain is in reverse", "order of Namespace (i.e. Users of Namespace com.att.myapp would be", @@ -2384,18 +2385,18 @@ public class AuthzCassServiceImpl createUserCred(final AuthzTrans trans, REQUEST from) { final String cmdDescription = ("Create User Credential"); TimeTaken tt = trans.start(cmdDescription, Env.SUB); - + try { Result rcred = mapper.cred(trans, from, true); if (rcred.isOKhasData()) { rcred = ques.userCredSetup(trans, rcred.value); - + final ServiceValidator v = new ServiceValidator(); - - if (v.cred(trans, trans.org(),rcred,true).err()) { // Note: Creates have stricter Validations + + if (v.cred(trans, trans.org(),rcred,true).err()) { // Note: Creates have stricter Validations return Result.err(Status.ERR_BadData,v.errs()); } - + // 2016-4 Jonathan, New Behavior - If MechID is not registered with Org, deny creation Identity mechID = null; @@ -2405,7 +2406,7 @@ public class AuthzCassServiceImpl > rlcd = ques.credDAO().readID(trans, rcred.value.id); if (rlcd.isOKhasData()) { @@ -2429,24 +2430,30 @@ public class AuthzCassServiceImpl TimeUnit.DAYS.toMillis(1)) { + return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists"); + } + } + } + } } else { try { // 2016-04-12 Jonathan If Caller is the Sponsor and is also an Owner of NS, allow without special Perm @@ -2462,32 +2469,32 @@ public class AuthzCassServiceImpl fd = mapper.future(trans,CredDAO.TABLE,from, rcred.value,false, // may want to enable in future. new Mapper.Memo() { @Override public String get() { - return cmdDescription + " [" + - cdd.id + '|' - + cdd.type + '|' + return cmdDescription + " [" + + cdd.id + '|' + + cdd.type + '|' + cdd.expires + ']'; } }, mc); - + switch(fd.status) { case OK: - Result rfc = func.createFuture(trans, fd.value, + Result rfc = func.createFuture(trans, fd.value, rcred.value.id + '|' + rcred.value.type.toString() + '|' + rcred.value.expires, trans.user(), nsr.value.get(0), FUTURE_OP.C); if (rfc.isOK()) { @@ -2495,25 +2502,32 @@ public class AuthzCassServiceImpl > admins = func.getAdmins(trans, nsr.value.get(0).name, false); - // OK, it's a first ID, and not by NS Admin, so let's set TempPassword length - // Note, we only do this on First time, because of possibility of - // prematurely expiring a production id - if (admins.isOKhasData() && !admins.value.contains(trans.user())) { - rcred.value.expires = org.expiration(null, Expiration.TempPassword).getTime(); + // OK, it's a first ID, and not by NS Owner + if(!ques.isOwner(trans,trans.user(),cdd.ns)) { + // Admins are not allowed to set first Cred, but Org has already + // said entity MAY create, typically by Permission + // We can't know which reason they are allowed here, so we + // have to assume that any with Special Permission would not be + // an Admin. + if(ques.isAdmin(trans, trans.user(), cdd.ns)) { + return Result.err(Result.ERR_Denied, + "Only Owners may create first passwords in their Namespace. Admins may modify after one exists" ); + } else { + // Allow IDs that AREN'T part of NS with Org Onboarding Permission (see Org object) to create Temp Passwords. + rcred.value.expires = org.expiration(null, Expiration.TempPassword).getTime(); + } } } } catch (Exception e) { trans.error().log(e, "While setting expiration to TempPassword"); } - + Resultudr = ques.credDAO().create(trans, rcred.value); if (udr.isOK()) { return Result.ok(); @@ -2531,12 +2545,12 @@ public class AuthzCassServiceImpl rnd = ques.deriveNs(trans,ns); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } - + TimeTaken tt = trans.start("MAP Creds by NS to Creds", Env.SUB); - try { + try { USERS users = mapper.newInstance(API.USERS); Result> rlcd = ques.credDAO().readNS(trans, ns); - + if (rlcd.isOK()) { if (!rlcd.isEmpty()) { return mapper.cred(rlcd.value, users); } - return Result.ok(users); + return Result.ok(users); } else { return Result.err(rlcd); } } finally { tt.done(); } - + } - @ApiDoc( - method = GET, + @ApiDoc( + method = GET, path = "/authn/creds/id/:ns", params = {"id|string|true"}, expectedCode = 200, - errorCodes = {403,404,406}, + errorCodes = {403,404,406}, text = { "Return all IDs in for ID" ,"(because IDs are multiple, due to multiple Expiration Dates)" } @@ -2592,59 +2606,59 @@ public class AuthzCassServiceImpl rnd = ques.deriveNs(trans,ns); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } - + TimeTaken tt = trans.start("MAP Creds by ID to Creds", Env.SUB); - try { + try { USERS users = mapper.newInstance(API.USERS); Result> rlcd = ques.credDAO().readID(trans, id); - + if (rlcd.isOK()) { if (!rlcd.isEmpty()) { return mapper.cred(rlcd.value, users); } - return Result.ok(users); + return Result.ok(users); } else { return Result.err(rlcd); } } finally { tt.done(); } - + } - @ApiDoc( - method = GET, + @ApiDoc( + method = GET, path = "/authn/certs/id/:id", params = {"id|string|true"}, expectedCode = 200, - errorCodes = {403,404,406}, + errorCodes = {403,404,406}, text = { "Return Cert Info for ID" } ) @Override public Result getCertInfoByID(AuthzTrans trans, HttpServletRequest req, String id) { TimeTaken tt = trans.start("Get Cert Info by ID", Env.SUB); - try { + try { CERTS certs = mapper.newInstance(API.CERTS); Result> rlcd = ques.certDAO().readID(trans, id); - + if (rlcd.isOK()) { if (!rlcd.isEmpty()) { return mapper.cert(rlcd.value, certs); } - return Result.ok(certs); - } else { + return Result.ok(certs); + } else { return Result.err(rlcd); } } finally { @@ -2653,12 +2667,12 @@ public class AuthzCassServiceImpl rcred = mapper.cred(trans, from, true); if (rcred.isOKhasData()) { rcred = ques.userCredSetup(trans, rcred.value); - + final ServiceValidator v = new ServiceValidator(); - - if (v.cred(trans, trans.org(),rcred,false).err()) {// Note: Creates have stricter Validations + + if (v.cred(trans, trans.org(),rcred,false).err()) {// Note: Creates have stricter Validations return Result.err(Status.ERR_BadData,v.errs()); } Result> rlcd = ques.credDAO().readID(trans, rcred.value.id); if (rlcd.notOKorIsEmpty()) { return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); - } - + } + MayChange mc = new MayChangeCred(trans, rcred.value,MayChangeCred.RESET); - Result rmc = mc.mayChange(); + Result rmc = mc.mayChange(); if (rmc.notOK()) { return Result.err(rmc); } - + List lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); - + Result ri = selectEntryIfMultiple((CredRequest)from, lcdd, MayChangeCred.RESET); if (ri.notOK()) { return Result.err(ri); } int entry = ri.value; - - + + final CredDAO.Data cred = rcred.value; - + Result fd = mapper.future(trans,CredDAO.TABLE,from, rcred.value,false, new Mapper.Memo() { @Override public String get() { - return cmdDescription + " [" + - cred.id + '|' - + cred.type + '|' + return cmdDescription + " [" + + cred.id + '|' + + cred.type + '|' + cred.expires + ']'; } }, mc); - + Result> nsr = ques.nsDAO().read(trans, rcred.value.ns); if (nsr.notOKorIsEmpty()) { return Result.err(nsr); } - + switch(fd.status) { case OK: - Result rfc = func.createFuture(trans, fd.value, + Result rfc = func.createFuture(trans, fd.value, rcred.value.id + '|' + rcred.value.type.toString() + '|' + rcred.value.expires, trans.user(), nsr.value.get(0), FUTURE_OP.U); if (rfc.isOK()) { @@ -2727,7 +2741,7 @@ public class AuthzCassServiceImpl cred = mapper.cred(trans, from, false); Organization org = trans.org(); final ServiceValidator v = new ServiceValidator(); - if (v.notOK(cred).err() || + if (v.notOK(cred).err() || v.nullOrBlank(cred.value.id, "Invalid ID").err() || v.user(org,cred.value.id).err()) { return Result.err(Status.ERR_BadData,v.errs()); } - + try { String reason; if ((reason=org.validate(trans, Policy.MAY_EXTEND_CRED_EXPIRES, new CassExecutor(trans,func)))!=null) { @@ -2809,19 +2823,19 @@ public class AuthzCassServiceImpl > rlcd = ques.credDAO().readID(trans, cred.value.id); if (rlcd.notOKorIsEmpty()) { return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); } - + // Only Passwords can be extended List lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); //Need to do the "Pick Entry" mechanism // Note, this sorts - Result ri = selectEntryIfMultiple((CredRequest)from, lcdd, "extend"); + Result ri = selectEntryIfMultiple((CredRequest)from, lcdd, MayChangeCred.EXTEND); if (ri.notOK()) { return Result.err(ri); } @@ -2835,9 +2849,12 @@ public class AuthzCassServiceImpl deleteUserCred(AuthzTrans trans, REQUEST from) { - final Result cred = mapper.cred(trans, from, false); - final Validator v = new ServiceValidator(); - if (v.nullOrBlank("cred", cred.value.id).err()) { - return Result.err(Status.ERR_BadData,v.errs()); - } - - MayChange mc = new MayChangeCred(trans,cred.value,MayChangeCred.DELETE); - Result rmc = mc.mayChange(); - if (rmc.notOK()) { - return Result.err(rmc); - } - - boolean doForce = trans.requested(force); - Result> rlcd = ques.credDAO().readID(trans, cred.value.id); - if (rlcd.notOKorIsEmpty()) { - // Empty Creds should not have user_roles. - Result> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); - if (rlurd.isOKhasData()) { - for (UserRoleDAO.Data data : rlurd.value) { - ques.userRoleDAO().delete(trans, data, false); - } - } - return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); - } - boolean isLastCred = rlcd.value.size()==1; - - int entry = -1; - int fentry = entry; - if(cred.value.type==CredDAO.FQI) { - entry = -1; - for(CredDAO.Data cdd : rlcd.value) { - ++fentry; - if(cdd.type == CredDAO.FQI) { - entry = fentry; - break; - } - } - } else { - if (!doForce) { - if (rlcd.value.size() > 1) { - CredRequest cr = (CredRequest)from; - String inputOption = cr.getEntry(); - if (inputOption == null) { - List list = filterList(rlcd.value,CredDAO.BASIC_AUTH,CredDAO.BASIC_AUTH_SHA256,CredDAO.CERT_SHA256_RSA); - String message = selectCredFromList(list, MayChangeCred.DELETE); - Object[] variables = buildVariables(list); - return Result.err(Status.ERR_ChoiceNeeded, message, variables); - } else { - try { - if (inputOption.length()>5) { // should be a date - Date d = Chrono.xmlDatatypeFactory.newXMLGregorianCalendar(inputOption).toGregorianCalendar().getTime(); - for (CredDAO.Data cd : rlcd.value) { - ++fentry; - if (cd.type.equals(cr.getType()) && cd.expires.equals(d)) { - entry = fentry; - break; - } - } - } else { - entry = Integer.parseInt(inputOption) - 1; - int count = 0; - for (CredDAO.Data cd : rlcd.value) { - if(cd.type!=CredDAO.BASIC_AUTH && cd.type!=CredDAO.BASIC_AUTH_SHA256 && cd.type!=CredDAO.CERT_SHA256_RSA) { - ++entry; - } - if(++count>entry) { - break; - } - } - } - } catch (NullPointerException e) { - return Result.err(Status.ERR_BadData, "Invalid Date Format for Entry"); - } catch (NumberFormatException e) { - return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); - } - } - isLastCred = (entry==-1)?true:false; - } else { - isLastCred = true; - } - if (entry < -1 || entry >= rlcd.value.size()) { - return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); - } - } - } - - Result fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, - () -> "Delete Credential [" + - cred.value.id + - ']', - mc); - - Result> nsr = ques.nsDAO().read(trans, cred.value.ns); - if (nsr.notOKorIsEmpty()) { - return Result.err(nsr); - } - - switch(fd.status) { - case OK: - Result rfc = func.createFuture(trans, fd.value, cred.value.id, - trans.user(), nsr.value.get(0), FUTURE_OP.D); - - if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "Credential Delete [%s] is saved for future processing",cred.value.id); - } else { - return Result.err(rfc); - } - case Status.ACC_Now: - Resultudr = null; - if (!trans.requested(force)) { - if (entry<0 || entry >= rlcd.value.size()) { - if(cred.value.type==CredDAO.FQI) { - return Result.err(Status.ERR_BadData,"FQI does not exist"); - } else { - return Result.err(Status.ERR_BadData,"Invalid Choice [" + entry + "] chosen for Delete [%s] is saved for future processing",cred.value.id); - } - } - udr = ques.credDAO().delete(trans, rlcd.value.get(entry),false); - } else { - for (CredDAO.Data curr : rlcd.value) { - udr = ques.credDAO().delete(trans, curr, false); - if (udr.notOK()) { - return Result.err(udr); - } - } - } - if (isLastCred) { - Result> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); - if (rlurd.isOK()) { - for (UserRoleDAO.Data data : rlurd.value) { - ques.userRoleDAO().delete(trans, data, false); - } - } - } - if (udr==null) { - return Result.err(Result.ERR_NotFound,"No User Data found"); - } - if (udr.isOK()) { - return Result.ok(); - } - return Result.err(udr); - default: - return Result.err(fd); - } - - } - - /* - * Codify the way to get Either Choice Needed or actual Integer from Credit Request - */ - private Result selectEntryIfMultiple(final CredRequest cr, List lcd, String action) { - int entry = 0; - if (lcd.size() > 1) { - String inputOption = cr.getEntry(); - if (inputOption == null) { - String message = selectCredFromList(lcd, action); - Object[] variables = buildVariables(lcd); - return Result.err(Status.ERR_ChoiceNeeded, message, variables); - } else { - entry = Integer.parseInt(inputOption) - 1; - } - if (entry < 0 || entry >= lcd.size()) { - return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); - } - } - return Result.ok(entry); - } - - private List filterList(List orig, Integer ... types) { - List rv = new ArrayList<>(); + } + + @ApiDoc( + method = DELETE, + path = "/authn/cred", + params = {}, + expectedCode = 200, + errorCodes = {300,403,404,406}, + text = { "Delete a Credential. If multiple credentials exist for this", + "ID, you will need to specify which entry you are deleting in the", + "CredRequest object." + } + ) + @Override + public Result deleteUserCred(AuthzTrans trans, REQUEST from) { + final Result cred = mapper.cred(trans, from, false); + final Validator v = new ServiceValidator(); + if (v.nullOrBlank("cred", cred.value.id).err()) { + return Result.err(Status.ERR_BadData,v.errs()); + } + + MayChange mc = new MayChangeCred(trans,cred.value,MayChangeCred.DELETE); + Result rmc = mc.mayChange(); + if (rmc.notOK()) { + return Result.err(rmc); + } + + boolean doForce = trans.requested(force); + Result> rlcd = ques.credDAO().readID(trans, cred.value.id); + if (rlcd.notOKorIsEmpty()) { + // Empty Creds should not have user_roles. + Result> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); + if (rlurd.isOKhasData()) { + for (UserRoleDAO.Data data : rlurd.value) { + ques.userRoleDAO().delete(trans, data, false); + } + } + return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); + } + boolean isLastCred = rlcd.value.size()==1; + + int entry; + CredRequest cr = (CredRequest)from; + if(isLastCred) { + if(cr.getEntry()==null || "1".equals(cr.getEntry())) { + entry = 0; + } else { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } else { + entry = -1; + int fentry = entry; + if(cred.value.type==CredDAO.FQI) { + entry = -1; + for(CredDAO.Data cdd : rlcd.value) { + ++fentry; + if(cdd.type == CredDAO.FQI) { + entry = fentry; + break; + } + } + } else { + if (!doForce) { + if (rlcd.value.size() > 1) { + String inputOption = cr.getEntry(); + if (inputOption == null) { + List list = filterList(rlcd.value,CredDAO.BASIC_AUTH,CredDAO.BASIC_AUTH_SHA256,CredDAO.CERT_SHA256_RSA); + String message = selectCredFromList(list, MayChangeCred.DELETE); + Object[] variables = buildVariables(list); + return Result.err(Status.ERR_ChoiceNeeded, message, variables); + } else { + try { + if (inputOption.length()>5) { // should be a date + Date d = Chrono.xmlDatatypeFactory.newXMLGregorianCalendar(inputOption).toGregorianCalendar().getTime(); + for (CredDAO.Data cd : rlcd.value) { + ++fentry; + if (cd.type.equals(cr.getType()) && cd.expires.equals(d)) { + entry = fentry; + break; + } + } + } else { + entry = Integer.parseInt(inputOption) - 1; + int count = 0; + for (CredDAO.Data cd : rlcd.value) { + if(cd.type!=CredDAO.BASIC_AUTH && cd.type!=CredDAO.BASIC_AUTH_SHA256 && cd.type!=CredDAO.CERT_SHA256_RSA) { + ++entry; + } + if(++count>entry) { + break; + } + } + } + } catch (NullPointerException e) { + return Result.err(Status.ERR_BadData, "Invalid Date Format for Entry"); + } catch (NumberFormatException e) { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } + isLastCred = (entry==-1); + } else { + isLastCred = true; + } + if (entry < -1 || entry >= rlcd.value.size()) { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } + } + } + + Result fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, + () -> "Delete Credential [" + + cred.value.id + + ']', + mc); + + Result> nsr = ques.nsDAO().read(trans, cred.value.ns); + if (nsr.notOKorIsEmpty()) { + return Result.err(nsr); + } + + switch(fd.status) { + case OK: + Result rfc = func.createFuture(trans, fd.value, cred.value.id, + trans.user(), nsr.value.get(0), FUTURE_OP.D); + + if (rfc.isOK()) { + return Result.err(Status.ACC_Future, "Credential Delete [%s] is saved for future processing",cred.value.id); + } else { + return Result.err(rfc); + } + case Status.ACC_Now: + Resultudr = null; + if (!trans.requested(force)) { + if (entry<0 || entry >= rlcd.value.size()) { + if(cred.value.type==CredDAO.FQI) { + return Result.err(Status.ERR_BadData,"FQI does not exist"); + } else { + return Result.err(Status.ERR_BadData,"Invalid Choice [" + entry + "] chosen for Delete [%s] is saved for future processing",cred.value.id); + } + } + udr = ques.credDAO().delete(trans, rlcd.value.get(entry),false); + } else { + for (CredDAO.Data curr : rlcd.value) { + udr = ques.credDAO().delete(trans, curr, false); + if (udr.notOK()) { + return Result.err(udr); + } + } + } + if (isLastCred) { + Result> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); + if (rlurd.isOK()) { + for (UserRoleDAO.Data data : rlurd.value) { + ques.userRoleDAO().delete(trans, data, false); + } + } + } + if (udr==null) { + return Result.err(Result.ERR_NotFound,"No User Data found"); + } + if (udr.isOK()) { + return Result.ok(); + } + return Result.err(udr); + default: + return Result.err(fd); + } + + } + + /* + * Codify the way to get Either Choice Needed or actual Integer from Credit Request + */ + private Result selectEntryIfMultiple(final CredRequest cr, List lcd, String action) { + int entry = 0; + if (lcd.size() > 1) { + String inputOption = cr.getEntry(); + if (inputOption == null) { + String message = selectCredFromList(lcd, action); + Object[] variables = buildVariables(lcd); + return Result.err(Status.ERR_ChoiceNeeded, message, variables); + } else { + if(MayChangeCred.EXTEND.equals(action)) { + // might be Tag + if(inputOption.length()>4) { //Tag is at least 12 + int e = 0; + CredDAO.Data last = null; + int lastIdx = -1; + for(CredDAO.Data cdd : lcd) { + if(inputOption.equals(cdd.tag)) { + if(last==null) { + last = cdd; + lastIdx = e; + } else { + if(last.expires.before(cdd.expires)) { + last = cdd; + lastIdx = e; + } + } + } + ++e; + } + if(last!=null) { + return Result.ok(lastIdx); + } + return Result.err(Status.ERR_BadData, "User chose unknown Tag"); + } + } + entry = Integer.parseInt(inputOption) - 1; + } + if (entry < 0 || entry >= lcd.size()) { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } + return Result.ok(entry); + } + + private List filterList(List orig, Integer ... types) { + List rv = new ArrayList<>(); for(CredDAO.Data cdd : orig) { - if(cdd!=null) { - for(int t : types) { - if(t==cdd.type) { - rv.add(cdd); - } - } - } - } - return rv; - } - - private String[] buildVariables(List value) { - // ensure credentials are sorted so we can fully automate Cred regression test - Collections.sort(value, (cred1, cred2) -> - cred1.type==cred2.type?cred2.expires.compareTo(cred1.expires): - cred1.type { + if(o1.type==o2.type) { + return o1.expires.compareTo(o2.expires); + } else { + return o1.type.compareTo(o2.type); + } + }); + return rv; + } + + private String[] buildVariables(List value) { String [] vars = new String[value.size()]; CredDAO.Data cdd; - + for (int i = 0; i < value.size(); i++) { - cdd = value.get(i); - vars[i] = cdd.id + TWO_SPACE + cdd.type + TWO_SPACE + (cdd.type<10?TWO_SPACE:"")+ cdd.expires + TWO_SPACE + cdd.tag; + cdd = value.get(i); + vars[i] = cdd.id + TWO_SPACE + Define.getCredType(cdd.type) + TWO_SPACE + Chrono.niceUTCStamp(cdd.expires) + TWO_SPACE + cdd.tag; } return vars; } - + private String selectCredFromList(List value, String action) { StringBuilder errMessage = new StringBuilder(); String userPrompt = MayChangeCred.DELETE.equals(action)? - "Select which cred to delete (set force=true to delete all):": - "Select which cred to " + action + ':'; + "Select which cred to delete (set force=true to delete all):": + "Select which cred to " + action + ':'; int numSpaces = value.get(0).id.length() - "Id".length(); - + errMessage.append(userPrompt + '\n'); errMessage.append(" ID"); for (int i = 0; i < numSpaces; i++) { errMessage.append(' '); } - errMessage.append(" Type Expires Tag " + '\n'); + errMessage.append(" Type Expires Tag " + '\n'); for (int i=0;i fd = mapper.future(trans,UserRoleDAO.TABLE,from,urr.value,true, // may request Approvals () -> "Add User [" + userRole.user + "] to Role [" + @@ -3193,9 +3251,9 @@ public class AuthzCassServiceImpl nsd; @Override public Result mayChange() { - if(urr.value.role.startsWith(urr.value.user)) { - return Result.ok((NsDAO.Data)null); - } + if(urr.value.role.startsWith(urr.value.user)) { + return Result.ok((NsDAO.Data)null); + } if (nsd==null) { RoleDAO.Data r = RoleDAO.Data.decode(userRole); nsd = ques.mayUser(trans, trans.user(), r, Access.write); @@ -3203,30 +3261,30 @@ public class AuthzCassServiceImpl nsr = ques.deriveNs(trans, userRole.role); - if (nsr.notOK()) { - return Result.err(nsr); - } - ndd = nsr.value; + Result nsr = ques.deriveNs(trans, userRole.role); + if (nsr.notOK()) { + return Result.err(nsr); + } + ndd = nsr.value; } switch(fd.status) { case OK: - Result rfc = func.createFuture(trans, fd.value, userRole.user+'|'+userRole.ns + '.' + userRole.rname, + Result rfc = func.createFuture(trans, fd.value, userRole.user+'|'+userRole.ns + '.' + userRole.rname, userRole.user, ndd, FUTURE_OP.C); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "UserRole [%s - %s.%s] is saved for future processing", userRole.user, userRole.ns, userRole.rname); - } else { + } else { return Result.err(rfc); } case Status.ACC_Now: @@ -3238,7 +3296,7 @@ public class AuthzCassServiceImpl rrdd; rrdd = RoleDAO.Data.decode(trans,ques,role); if (rrdd.notOK()) { @@ -3268,11 +3326,11 @@ public class AuthzCassServiceImpl userSet = new HashSet<>(); Result> rlurd = ques.userRoleDAO().readByRole(trans, role); @@ -3281,7 +3339,7 @@ public class AuthzCassServiceImpl > rlurd = ques.userRoleDAO().readByUser(trans, user); - if (rlurd.notOK()) { + if (rlurd.notOK()) { return Result.err(rlurd); } - + /* Check for - * 1) is User + * 1) is User * 2) is User's Supervisor * 3) Has special global access =read permission - * + * * If none of the 3, then filter results to NSs in which Calling User has Ns.access * read */ boolean mustFilter; @@ -3343,11 +3401,11 @@ public class AuthzCassServiceImpl content; if (mustFilter) { content = new ArrayList<>(rlurd.value.size()); // avoid multi-memory redos - + for (UserRoleDAO.Data data : rlurd.value) { ndd.name=data.ns; Result mur = ques.mayUser(trans, callingUser, ndd, Access.read); @@ -3355,7 +3413,7 @@ public class AuthzCassServiceImpl rrdd = RoleDAO.Data.decode(trans,ques,role); if (rrdd.notOK()) { return Result.err(rrdd); } - + Result rcr = ques.mayUser(trans, trans.user(), rrdd.value, Access.write); boolean mayNotChange; if ((mayNotChange = rcr.notOK()) && !trans.requested(future)) { return Result.err(rcr); } - + Result> rr = ques.userRoleDAO().read(trans, user,role); if (rr.notOK()) { return Result.err(rr); @@ -3423,7 +3481,7 @@ public class AuthzCassServiceImpl rfc = func.createFuture(trans, fto, + Result rfc = func.createFuture(trans, fto, userRole.user+'|'+userRole.role, userRole.user, rcr.value, FUTURE_OP.U); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "UserRole [%s - %s] is saved for future processing", @@ -3439,14 +3497,14 @@ public class AuthzCassServiceImpl rns = ques.mayUser(trans, trans.user(), rdd, Access.write); @@ -3471,7 +3529,7 @@ public class AuthzCassServiceImpl rfc = func.createFuture(trans, fto, + Result rfc = func.createFuture(trans, fto, userRole.user+'|'+userRole.role, userRole.user, rns.value, FUTURE_OP.D); if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "UserRole [%s - %s] is saved for future processing", + return Result.err(Status.ACC_Future, "UserRole [%s - %s] is saved for future processing", userRole.user, userRole.role); - } else { + } else { return Result.err(rfc); } } else { @@ -3507,13 +3565,13 @@ public class AuthzCassServiceImpl ns = ques.deriveNs(trans, role); // if (ns.notOK()) return Result.err(ns); -// +// // Result rnd = ques.mayUser(trans, trans.user(), ns.value, Access.write); // May calling user see by virtue of the Role Result rrdd = RoleDAO.Data.decode(trans, ques, role); @@ -3535,9 +3593,9 @@ public class AuthzCassServiceImpl rnd = ques.mayUser(trans, trans.user(), rrdd.value,Access.read); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } - + HashSet userSet = new HashSet<>(); Result> rlurd = ques.userRoleDAO().readUserInRole(trans, user, role); if (rlurd.isOK()) { @@ -3545,20 +3603,20 @@ public class AuthzCassServiceImpl ns = ques.deriveNs(trans, role); // if (ns.notOK()) return Result.err(ns); -// +// // Result rnd = ques.mayUser(trans, trans.user(), ns.value, Access.write); // May calling user see by virtue of the Role Result rrdd = RoleDAO.Data.decode(trans, ques, role); if (rrdd.notOK()) { return Result.err(rrdd); } - + boolean contactOnly = false; // Allow the request of any valid user to find the contact of the NS (Owner) Result rnd = ques.mayUser(trans, trans.user(), rrdd.value,Access.read); @@ -3589,10 +3647,10 @@ public class AuthzCassServiceImpl userSet = new HashSet<>(); Result> rlurd = ques.userRoleDAO().readByRole(trans, role); - if (rlurd.isOK()) { + if (rlurd.isOK()) { for (UserRoleDAO.Data data : rlurd.value) { if (contactOnly) { //scrub data // Can't change actual object, or will mess up the cache. @@ -3607,7 +3665,7 @@ public class AuthzCassServiceImpl > nsd = ques.nsDAO().read(trans, nss.value.ns); if (nsd.notOK()) { return Result.err(nsd); } - + boolean allInstance = ASTERIX.equals(instance); boolean allAction = ASTERIX.equals(action); - // Get list of roles per Permission, + // Get list of roles per Permission, // Then loop through Roles to get Users // Note: Use Sets to avoid processing or responding with Duplicates Set roleUsed = new HashSet<>(); Set userSet = new HashSet<>(); - + if (!nss.isEmpty()) { Result> rlp = ques.permDAO().readByType(trans, nss.value.ns, nss.value.name); if (rlp.isOKhasData()) { for (PermDAO.Data pd : rlp.value) { - if ((allInstance || pd.instance.equals(instance)) && + if ((allInstance || pd.instance.equals(instance)) && (allAction || pd.action.equals(action))) { if (ques.mayUser(trans, trans.user(),pd,Access.read).isOK()) { for (String role : pd.roles) { @@ -3687,10 +3745,10 @@ public class AuthzCassServiceImpl getHistoryByUser(final AuthzTrans trans, String user, final int[] yyyymm, final int sort) { + public Result getHistoryByUser(final AuthzTrans trans, String user, final int[] yyyymm, final int sort) { final Validator v = new ServiceValidator(); if (v.nullOrBlank("User",user).err()) { return Result.err(Status.ERR_BadData,v.errs()); @@ -3739,12 +3797,12 @@ public class AuthzCassServiceImpl rnd = ques.mayUser(trans, trans.user(), rrdd.value, Access.read); if (rnd.notOK()) { return Result.err(rnd); } - Result> resp = ques.historyDAO().readBySubject(trans, role, "role", yyyymm); + Result> resp = ques.historyDAO().readBySubject(trans, role, "role", yyyymm); if (resp.notOK()) { return Result.err(resp); } @@ -3762,19 +3820,19 @@ public class AuthzCassServiceImpl > resp; if(type.startsWith(trans.user())) { - resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); + resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); } else { Result rnd = ques.deriveNs(trans,type); - if (rnd.notOK()) { - return Result.err(rnd); - } - rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); - if (rnd.notOK()) { - return Result.err(rnd); - } - resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); - } - + if (rnd.notOK()) { + return Result.err(rnd); + } + rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); + if (rnd.notOK()) { + return Result.err(rnd); + } + resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); + } + if (resp.notOK()) { return Result.err(resp); } @@ -3784,7 +3842,7 @@ public class AuthzCassServiceImpl getHistoryByNS(AuthzTrans trans, String ns, int[] yyyymm, final int sort) { final Validator v = new ServiceValidator(); - if (v.nullOrBlank("NS",ns).err()) { + if (v.nullOrBlank("NS",ns).err()) { return Result.err(Status.ERR_BadData,v.errs()); } @@ -3794,7 +3852,7 @@ public class AuthzCassServiceImpl > resp = ques.historyDAO().readBySubject(trans, ns, "ns", yyyymm); @@ -3806,11 +3864,11 @@ public class AuthzCassServiceImpl getHistoryBySubject(AuthzTrans trans, String subject, String target, int[] yyyymm, final int sort) { - NsDAO.Data ndd = new NsDAO.Data(); - ndd.name = FQI.reverseDomain(subject); + NsDAO.Data ndd = new NsDAO.Data(); + ndd.name = FQI.reverseDomain(subject); Result rnd = ques.mayUser(trans, trans.user(), ndd, Access.read); if (rnd.notOK()) { - return Result.err(rnd); + return Result.err(rnd); } Result> resp = ques.historyDAO().readBySubject(trans, subject, target, yyyymm); @@ -3821,7 +3879,7 @@ public class AuthzCassServiceImpl createDelegate(final AuthzTrans trans, REQUEST base) { @@ -3837,23 +3895,23 @@ public class AuthzCassServiceImpl createOrUpdateDelegate(final AuthzTrans trans, REQUEST base, final Access access) { final Result rd = mapper.delegate(trans, base); final ServiceValidator v = new ServiceValidator(); - if (v.delegate(trans.org(),rd).err()) { + if (v.delegate(trans.org(),rd).err()) { return Result.err(Status.ERR_BadData,v.errs()); } final DelegateDAO.Data dd = rd.value; - + Result> ddr = ques.delegateDAO().read(trans, dd); if (access==Access.create && ddr.isOKhasData()) { return Result.err(Status.ERR_ConflictAlreadyExists, "[%s] already delegates to [%s]", dd.user, ddr.value.get(0).delegate); - } else if (access!=Access.create && ddr.notOKorIsEmpty()) { + } else if (access!=Access.create && ddr.notOKorIsEmpty()) { return Result.err(Status.ERR_NotFound, "[%s] does not have a Delegate Record to [%s].",dd.user,access.name()); } Result rv = ques.mayUser(trans, dd, access); if (rv.notOK()) { return rv; } - + Result fd = mapper.future(trans,DelegateDAO.TABLE,base, dd, false, () -> { StringBuilder sb = new StringBuilder(); @@ -3870,15 +3928,15 @@ public class AuthzCassServiceImpl { return Result.ok(); // Validate in code above }); - + switch(fd.status) { case OK: - Result rfc = func.createFuture(trans, fd.value, + Result rfc = func.createFuture(trans, fd.value, dd.user, trans.user(),null, access==Access.create?FUTURE_OP.C:FUTURE_OP.U); - if (rfc.isOK()) { + if (rfc.isOK()) { return Result.err(Status.ACC_Future, "Delegate for [%s]", dd.user); - } else { + } else { return Result.err(rfc); } case Status.ACC_Now: @@ -3904,7 +3962,7 @@ public class AuthzCassServiceImpl > ddl; if ((ddl=ques.delegateDAO().read(trans, rd.value)).notOKorIsEmpty()) { return Result.err(Status.ERR_DelegateNotFound,"Cannot delete non-existent Delegate"); @@ -3914,7 +3972,7 @@ public class AuthzCassServiceImpl getDelegatesByUser(AuthzTrans trans, String user) { final Validator v = new ServiceValidator(); @@ -3953,7 +4011,7 @@ public class AuthzCassServiceImpl > dbDelgs = ques.delegateDAO().read(trans, user); @@ -3965,7 +4023,7 @@ public class AuthzCassServiceImpl > curr; Lookup> apprByTicket=null; for (ApprovalDAO.Data updt : rlad.value) { @@ -4035,14 +4093,14 @@ public class AuthzCassServiceImpl >> delegateCache = new HashMap<>(); Map futureCache = new HashMap<>(); FutureDAO.Data hasDeleted = new FutureDAO.Data(); - + for (ApprovalDAO.Data cd : curr.value) { if ("pending".equals(cd.status)) { // Check for right record. Need ID, or (Ticket&Trans.User==Appr) // If Default ID boolean delegatedAction = ques.isDelegated(trans, user, cd.approver, delegateCache); String delegator = cd.approver; - if (updt.id!=null || + if (updt.id!=null || (updt.ticket!=null && user.equals(cd.approver)) || (updt.ticket!=null && delegatedAction)) { if (updt.ticket.equals(cd.ticket)) { @@ -4120,7 +4178,7 @@ public class AuthzCassServiceImpl getApprovalsByUser(AuthzTrans trans, String user) { final Validator v = new ServiceValidator(); - if (v.nullOrBlank("User", user).err()) { + if (v.nullOrBlank("User", user).err()) { return Result.err(Status.ERR_BadData,v.errs()); } @@ -4159,7 +4217,7 @@ public class AuthzCassServiceImpl getApprovalsByTicket(AuthzTrans trans, String ticket) { final Validator v = new ServiceValidator(); - if (v.nullOrBlank("Ticket", ticket).err()) { + if (v.nullOrBlank("Ticket", ticket).err()) { return Result.err(Status.ERR_BadData,v.errs()); } UUID uuid; @@ -4168,7 +4226,7 @@ public class AuthzCassServiceImpl > rapd = ques.approvalDAO().readByTicket(trans, uuid); if (rapd.isOK()) { return mapper.approvals(rapd.value); @@ -4176,23 +4234,23 @@ public class AuthzCassServiceImpl getApprovalsByApprover(AuthzTrans trans, String approver) { final Validator v = new ServiceValidator(); if (v.nullOrBlank("Approver", approver).err()) { return Result.err(Status.ERR_BadData,v.errs()); } - + List listRapds = new ArrayList<>(); - + Result> myRapd = ques.approvalDAO().readByApprover(trans, approver); if (myRapd.notOK()) { return Result.err(myRapd); } - + listRapds.addAll(myRapd.value); - + Result> delegatedFor = ques.delegateDAO().readByDelegate(trans, approver); if (delegatedFor.isOK()) { for (DelegateDAO.Data dd : delegatedFor.value) { @@ -4200,7 +4258,7 @@ public class AuthzCassServiceImpl > rapd = ques.approvalDAO().readByApprover(trans, delegator); if (rapd.isOK()) { - for (ApprovalDAO.Data d : rapd.value) { + for (ApprovalDAO.Data d : rapd.value) { if (!d.user.equals(trans.user())) { listRapds.add(d); } @@ -4209,10 +4267,10 @@ public class AuthzCassServiceImpl