Update for more Logging Info
[aaf/authz.git] / auth / auth-service / src / main / java / org / onap / aaf / auth / service / mapper / Mapper_2_0.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.auth.service.mapper;
23
24 import java.nio.ByteBuffer;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.Comparator;
29 import java.util.Date;
30 import java.util.GregorianCalendar;
31 import java.util.List;
32 import java.util.UUID;
33
34 import javax.xml.datatype.XMLGregorianCalendar;
35
36 import org.onap.aaf.auth.dao.Bytification;
37 import org.onap.aaf.auth.dao.cass.ApprovalDAO;
38 import org.onap.aaf.auth.dao.cass.CertDAO;
39 import org.onap.aaf.auth.dao.cass.CredDAO;
40 import org.onap.aaf.auth.dao.cass.DelegateDAO;
41 import org.onap.aaf.auth.dao.cass.FutureDAO;
42 import org.onap.aaf.auth.dao.cass.HistoryDAO;
43 import org.onap.aaf.auth.dao.cass.Namespace;
44 import org.onap.aaf.auth.dao.cass.NsSplit;
45 import org.onap.aaf.auth.dao.cass.NsType;
46 import org.onap.aaf.auth.dao.cass.PermDAO;
47 import org.onap.aaf.auth.dao.cass.RoleDAO;
48 import org.onap.aaf.auth.dao.cass.Status;
49 import org.onap.aaf.auth.dao.cass.UserRoleDAO;
50 import org.onap.aaf.auth.dao.cass.DelegateDAO.Data;
51 import org.onap.aaf.auth.dao.hl.Question;
52 import org.onap.aaf.auth.dao.hl.Question.Access;
53 import org.onap.aaf.auth.env.AuthzTrans;
54 import org.onap.aaf.auth.env.AuthzTrans.REQD_TYPE;
55 import org.onap.aaf.auth.layer.Result;
56 import org.onap.aaf.auth.org.Organization;
57 import org.onap.aaf.auth.org.Organization.Expiration;
58 import org.onap.aaf.auth.rserv.Pair;
59 import org.onap.aaf.auth.service.MayChange;
60 import org.onap.aaf.cadi.aaf.marshal.CertsMarshal;
61 import org.onap.aaf.cadi.util.Split;
62 import org.onap.aaf.cadi.util.Vars;
63 import org.onap.aaf.misc.env.Env;
64 import org.onap.aaf.misc.env.TimeTaken;
65 import org.onap.aaf.misc.env.util.Chrono;
66 import org.onap.aaf.misc.rosetta.Marshal;
67
68 import aaf.v2_0.Api;
69 import aaf.v2_0.Approval;
70 import aaf.v2_0.Approvals;
71 import aaf.v2_0.Certs;
72 import aaf.v2_0.Certs.Cert;
73 import aaf.v2_0.CredRequest;
74 import aaf.v2_0.Delg;
75 import aaf.v2_0.DelgRequest;
76 import aaf.v2_0.Delgs;
77 import aaf.v2_0.Error;
78 import aaf.v2_0.History;
79 import aaf.v2_0.History.Item;
80 import aaf.v2_0.Keys;
81 import aaf.v2_0.NsRequest;
82 import aaf.v2_0.Nss;
83 import aaf.v2_0.Nss.Ns;
84 import aaf.v2_0.Perm;
85 import aaf.v2_0.PermKey;
86 import aaf.v2_0.PermRequest;
87 import aaf.v2_0.Perms;
88 import aaf.v2_0.Pkey;
89 import aaf.v2_0.Request;
90 import aaf.v2_0.Role;
91 import aaf.v2_0.RolePermRequest;
92 import aaf.v2_0.RoleRequest;
93 import aaf.v2_0.Roles;
94 import aaf.v2_0.UserRole;
95 import aaf.v2_0.UserRoleRequest;
96 import aaf.v2_0.UserRoles;
97 import aaf.v2_0.Users;
98 import aaf.v2_0.Users.User;
99
100 public class Mapper_2_0 implements Mapper<Nss, Perms, Pkey, Roles, Users, UserRoles, Delgs, Certs, Keys, Request, History, Error, Approvals> {
101     private Question q;
102
103     public Mapper_2_0(Question q) {
104         this.q = q;
105     }
106     
107     /* (non-Javadoc)
108      * @see org.onap.aaf.auth.service.mapper.Mapper#ns(java.lang.Object, org.onap.aaf.auth.service.mapper.Mapper.Holder)
109      */
110     @Override
111     public Result<Namespace> ns(AuthzTrans trans, Request base) {
112         NsRequest from = (NsRequest)base;
113         Namespace namespace = new Namespace();
114         namespace.name = from.getName();
115         namespace.admin = from.getAdmin();
116         namespace.owner = from.getResponsible();
117         namespace.description = from.getDescription();
118         trans.checkpoint(namespace.name, Env.ALWAYS);
119         
120         NsType nt = NsType.fromString(from.getType());
121         if (nt.equals(NsType.UNKNOWN)) {
122             String ns = namespace.name;
123             int count = 0;
124             for (int i=ns.indexOf('.');
125                     i>=0;
126                     i=ns.indexOf('.',i+1)) {
127                 ++count;
128             }
129             switch(count) {
130                 case 0: nt = NsType.ROOT;break;
131                 case 1: nt = NsType.COMPANY;break;
132                 default: nt = NsType.APP;
133             }
134         }
135         namespace.type = nt.type;
136         
137         return Result.ok(namespace);
138     }
139
140     @Override
141     public Result<Nss> nss(AuthzTrans trans, Namespace from, Nss to) {
142         List<Ns> nss = to.getNs();
143         Ns ns = new Ns();
144         ns.setName(from.name);
145         if (from.admin!=null)ns.getAdmin().addAll(from.admin);
146         if (from.owner!=null)ns.getResponsible().addAll(from.owner);
147         if (from.attrib!=null) {
148             for (Pair<String,String> attrib : from.attrib) {
149                 Ns.Attrib toAttrib = new Ns.Attrib();
150                 toAttrib.setKey(attrib.x);
151                 toAttrib.setValue(attrib.y);
152                 ns.getAttrib().add(toAttrib);
153             }
154         }
155
156         ns.setDescription(from.description);
157         nss.add(ns);
158         return Result.ok(to);
159     }
160
161     /**
162      * Note: Prevalidate if NS given is allowed to be seen before calling
163      */
164     @Override
165     public Result<Nss> nss(AuthzTrans trans, Collection<Namespace> from, Nss to) {
166         List<Ns> nss = to.getNs();
167         for (Namespace nd : from) {
168             Ns ns = new Ns();
169             ns.setName(nd.name);
170             if (nd.admin!=null) {
171                 ns.getAdmin().addAll(nd.admin);
172             }
173             if (nd.owner!=null) {
174                 ns.getResponsible().addAll(nd.owner);
175             }
176             ns.setDescription(nd.description);
177             if (nd.attrib!=null) {
178                 for (Pair<String,String> attrib : nd.attrib) {
179                     Ns.Attrib toAttrib = new Ns.Attrib();
180                     toAttrib.setKey(attrib.x);
181                     toAttrib.setValue(attrib.y);
182                     ns.getAttrib().add(toAttrib);
183                 }
184             }
185
186             nss.add(ns);
187         }
188         return Result.ok(to);
189     }
190
191     @Override
192     public Result<Perms> perms(AuthzTrans trans, List<PermDAO.Data> from, Perms to, boolean filter) {
193         List<Perm> perms = to.getPerm();
194         final boolean addNS = trans.requested(REQD_TYPE.ns);
195         TimeTaken tt = trans.start("Filter Perms before return", Env.SUB);
196         try {
197             if (from!=null) {
198                 for (PermDAO.Data data : from) {
199                     if (!filter || q.mayUser(trans, trans.user(), data, Access.read).isOK()) {
200                         Perm perm = new Perm();
201                         perm.setType(data.fullType());
202                         perm.setInstance(data.instance);
203                         perm.setAction(data.action);
204                         perm.setDescription(data.description);
205                         if (addNS) {
206                             perm.setNs(data.ns);
207                         }
208                         for (String role : data.roles(false)) {
209                             perm.getRoles().add(role);
210                         }
211                         perms.add(perm);
212                     }
213                 }
214             }
215         } finally {
216             tt.done();
217         }
218          
219         tt = trans.start("Sort Perms", Env.SUB);
220         try {
221             Collections.sort(perms, new Comparator<Perm>() {
222                 @Override
223                 public int compare(Perm perm1, Perm perm2) {
224                     int typeCompare = perm1.getType().compareToIgnoreCase(perm2.getType());
225                     if (typeCompare == 0) {
226                         int instanceCompare = perm1.getInstance().compareToIgnoreCase(perm2.getInstance());
227                         if (instanceCompare == 0) {
228                             return perm1.getAction().compareToIgnoreCase(perm2.getAction());
229                         }
230                         return instanceCompare;
231                     }
232                     return typeCompare;
233                 }    
234             });
235         } finally {
236             tt.done();
237         }
238         return Result.ok(to);
239     }
240     
241     @Override
242     public Result<Perms> perms(AuthzTrans trans, List<PermDAO.Data> from, Perms to, String[] nss, boolean filter) {
243         List<Perm> perms = to.getPerm();
244         TimeTaken tt = trans.start("Filter Perms before return", Env.SUB);
245         try {
246             if (from!=null) {
247                 boolean inNSS;
248                 for (PermDAO.Data data : from) {
249                     inNSS=false;
250                     for (int i=0;!inNSS && i<nss.length;++i) {
251                         if (nss[i].equals(data.ns)) {
252                             inNSS=true;
253                         }
254                     }
255                     if (inNSS && (!filter || q.mayUser(trans, trans.user(), data, Access.read).isOK())) {
256                         Perm perm = new Perm();
257                         perm.setType(data.fullType());
258                         perm.setInstance(data.instance);
259                         perm.setAction(data.action);
260                         for (String role : data.roles(false)) {
261                             perm.getRoles().add(role);
262                         }
263                         perm.setDescription(data.description);
264                         perms.add(perm);
265                     }
266                 }
267             }
268         } finally {
269             tt.done();
270         }
271          
272         tt = trans.start("Sort Perms", Env.SUB);
273         try {
274             Collections.sort(perms, new Comparator<Perm>() {
275                 @Override
276                 public int compare(Perm perm1, Perm perm2) {
277                     int typeCompare = perm1.getType().compareToIgnoreCase(perm2.getType());
278                     if (typeCompare == 0) {
279                         int instanceCompare = perm1.getInstance().compareToIgnoreCase(perm2.getInstance());
280                         if (instanceCompare == 0) {
281                             return perm1.getAction().compareToIgnoreCase(perm2.getAction());
282                         }
283                         return instanceCompare;
284                     }
285                     return typeCompare;
286                 }    
287             });
288         } finally {
289             tt.done();
290         }
291         return Result.ok(to);
292     }
293
294     @Override
295     public Result<List<PermDAO.Data>> perms(AuthzTrans trans, Perms perms) {
296         List<PermDAO.Data> lpd = new ArrayList<>();
297         for (Perm p : perms.getPerm()) {
298             Result<NsSplit> nss = q.deriveNsSplit(trans, p.getType());
299             PermDAO.Data pd = new PermDAO.Data();
300             if (nss.isOK()) { 
301                 pd.ns=nss.value.ns;
302                 pd.type = nss.value.name;
303                 pd.instance = p.getInstance();
304                 pd.action = p.getAction();
305                 for (String role : p.getRoles()) {
306                     pd.roles(true).add(role);
307                 }
308                 lpd.add(pd);
309             } else {
310                 return Result.err(nss);
311             }
312         }
313         return Result.ok(lpd);
314     }
315
316     
317     @Override
318     public Result<PermDAO.Data> permkey(AuthzTrans trans, Pkey from) {
319         return q.permFrom(trans, from.getType(),from.getInstance(),from.getAction());
320     }
321     
322     @Override
323     public Result<PermDAO.Data> permFromRPRequest(AuthzTrans trans, Request req) {
324         RolePermRequest from = (RolePermRequest)req;
325         Pkey perm = from.getPerm();
326         if (perm==null)return Result.err(Status.ERR_NotFound, "Permission not found");
327         Result<NsSplit> nss = q.deriveNsSplit(trans, perm.getType());
328         PermDAO.Data pd = new PermDAO.Data();
329         if (nss.isOK()) { 
330             pd.ns=nss.value.ns;
331             pd.type = nss.value.name;
332             pd.instance = from.getPerm().getInstance();
333             pd.action = from.getPerm().getAction();
334             trans.checkpoint(pd.fullPerm(), Env.ALWAYS);
335             
336             String[] roles = {};
337             
338             if (from.getRole() != null) {
339                 roles = from.getRole().split(",");
340             }
341             for (String role : roles) { 
342                 pd.roles(true).add(role);
343             }
344             return Result.ok(pd);
345         } else {
346             return Result.err(nss);
347         }
348     }
349     
350     @Override
351     public Result<RoleDAO.Data> roleFromRPRequest(AuthzTrans trans, Request req) {
352         RolePermRequest from = (RolePermRequest)req;
353         Result<NsSplit> nss = q.deriveNsSplit(trans, from.getRole());
354         RoleDAO.Data rd = new RoleDAO.Data();
355         if (nss.isOK()) { 
356             rd.ns = nss.value.ns;
357             rd.name = nss.value.name;
358             trans.checkpoint(rd.fullName(), Env.ALWAYS);
359             return Result.ok(rd);
360         } else {
361             return Result.err(nss);
362         }
363     }
364     
365     @Override
366     public Result<PermDAO.Data> perm(AuthzTrans trans, Request req) {
367         PermRequest from = (PermRequest)req;
368         String type = from.getType();
369         if(type==null) {
370                 return Result.err(Result.ERR_BadData, "Invalid Perm Type");
371         }
372         PermDAO.Data pd = new PermDAO.Data();
373         if(type.contains("@")) {
374                 String[] split = Split.splitTrim(':', type);
375                 pd.ns = split[0];
376                 pd.type=split.length>1?split[1]:"";
377                 pd.instance = from.getInstance();
378                 pd.action = from.getAction();
379                 pd.description = from.getDescription();
380                 return Result.ok(pd);
381         }  else {
382                 Result<NsSplit> nss = q.deriveNsSplit(trans, from.getType());
383                 if (nss.isOK()) { 
384                     pd.ns=nss.value.ns;
385                     pd.type = nss.value.name;
386                     pd.instance = from.getInstance();
387                     pd.action = from.getAction();
388                     pd.description = from.getDescription();
389                     trans.checkpoint(pd.fullPerm(), Env.ALWAYS);
390                     return Result.ok(pd);
391                 } else {
392                     return Result.err(nss);
393                 }
394         }
395     }
396     
397     @Override
398     public Request ungrantRequest(AuthzTrans trans, String role, String type, String instance, String action) {
399         RolePermRequest rpr = new RolePermRequest();
400         Pkey pkey = new Pkey();
401         pkey.setType(type);
402         pkey.setInstance(instance);
403         pkey.setAction(action);
404         rpr.setPerm(pkey);
405         
406         rpr.setRole(role);
407         return rpr;
408     }
409
410     @Override
411     public Result<RoleDAO.Data> role(AuthzTrans trans, Request base) {
412         RoleRequest from = (RoleRequest)base;
413         Result<NsSplit> nss = q.deriveNsSplit(trans, from.getName());
414         if (nss.isOK()) {
415             RoleDAO.Data to = new RoleDAO.Data();
416             to.ns = nss.value.ns;
417             to.name = nss.value.name;
418             to.description = from.getDescription();
419             trans.checkpoint(to.fullName(), Env.ALWAYS);
420
421             return Result.ok(to);
422         } else {
423             return Result.err(nss);
424         }
425     }
426
427     /* (non-Javadoc)
428      * @see org.onap.aaf.auth.service.mapper.Mapper#roles(java.util.List)
429      */
430     @Override
431     public Result<Roles> roles(AuthzTrans trans, List<RoleDAO.Data> from, Roles to, boolean filter) {
432         final boolean needNS = trans.requested(REQD_TYPE.ns); 
433         for (RoleDAO.Data frole : from) {
434             // Only Add Data to view if User is allowed to see this Role
435             if (!filter || q.mayUser(trans, trans.user(), frole,Access.read).isOK()) {
436                 Role role = new Role();
437                 role.setName(frole.ns + '.' + frole.name);
438                 role.setDescription(frole.description);
439                 if (needNS) {
440                     role.setNs(frole.ns);
441                 }
442                 for (String p : frole.perms(false)) { // can see any Perms in the Role he has permission for
443                     Result<String[]> rpa = PermDAO.Data.decodeToArray(trans,q,p);
444                     if (rpa.notOK())
445                         return Result.err(rpa);
446                     
447                     String[] pa = rpa.value;
448                     Pkey pKey = new Pkey();
449                     pKey.setType(pa[0]+'.'+pa[1]);
450                     pKey.setInstance(pa[2]);
451                     pKey.setAction(pa[3]);
452                     role.getPerms().add(pKey);
453                 }
454                 to.getRole().add(role);
455             }
456         }
457         return Result.ok(to);
458     }
459
460     /*
461      * (non-Javadoc)
462      * @see org.onap.aaf.auth.service.mapper.Mapper#users(java.util.Collection, java.lang.Object)
463      * 
464      * Note: Prevalidate all data for permission to view
465      */
466     @Override
467     public Result<Users> users(AuthzTrans trans, Collection<UserRoleDAO.Data> from, Users to) {
468         List<User> cu = to.getUser();
469         for (UserRoleDAO.Data urd : from) {
470             User user = new User();
471             user.setId(urd.user);
472             if (urd.expires!=null) {
473                 user.setExpires(Chrono.timeStamp(urd.expires));
474             }
475             cu.add(user);
476         }
477         return Result.ok(to);
478     }
479
480     /*
481      * (non-Javadoc)
482      * @see org.onap.aaf.auth.service.mapper.Mapper#users(java.util.Collection, java.lang.Object)
483      * 
484      * Note: Prevalidate all data for permission to view
485      */
486     @Override
487     public Result<UserRoles> userRoles(AuthzTrans trans, Collection<UserRoleDAO.Data> from, UserRoles to) {
488         List<UserRole> cu = to.getUserRole();
489         for (UserRoleDAO.Data urd : from) {
490             UserRole ur = new UserRole();
491             ur.setUser(urd.user);
492             ur.setRole(urd.role);
493             ur.setExpires(Chrono.timeStamp(urd.expires));
494             cu.add(ur);
495         }
496         return Result.ok(to);
497     }
498
499     @Override
500     public Result<UserRoleDAO.Data> userRole(AuthzTrans trans, Request base) {
501         try {
502             UserRoleRequest from = (UserRoleRequest)base;
503
504             // Setup UserRoleData, either for immediate placement, or for futureIt i
505             UserRoleDAO.Data to = new UserRoleDAO.Data();
506             if (from.getUser() != null) {
507                 to.user = from.getUser();
508             }
509             if (from.getRole() != null) {
510                 to.role(trans,q,from.getRole());
511             }
512             to.expires = getExpires(trans.org(),Expiration.UserInRole,base,from.getUser());
513             trans.checkpoint(to.toString(), Env.ALWAYS);
514
515             return Result.ok(to);
516         } catch (Exception t) {
517             return Result.err(Status.ERR_BadData,t.getMessage());
518         }
519     }
520
521     @Override
522     public Result<CredDAO.Data> cred(AuthzTrans trans, Request base, boolean requiresPass) {
523         CredRequest from = (CredRequest)base;
524         CredDAO.Data to = new CredDAO.Data();
525         to.id=from.getId();
526         to.ns = Question.domain2ns(to.id);
527         to.type = from.getType();
528         if(to.type!=null && to.type==CredDAO.FQI) {
529                 to.cred = null;
530         } else {
531                 String passwd = from.getPassword();
532                 if (requiresPass) {
533                     String ok = trans.org().isValidPassword(trans, to.id,passwd);
534                     if (ok.length()>0) {
535                         return Result.err(Status.ERR_BadData,ok);
536                     }
537                 } else {
538                     to.type=0;
539                 }
540                 if (passwd != null) {
541                     to.cred = ByteBuffer.wrap(passwd.getBytes());
542                     to.type = CredDAO.RAW; 
543                 } else {
544                     to.type = CredDAO.FQI;
545                 }
546         }
547                 
548         // Note: Ensure requested EndDate created will match Organization Password Rules
549         //  P.S. Do not apply TempPassword rule here. Do that when you know you are doing a Create/Reset (see Service)
550         to.expires = getExpires(trans.org(),Expiration.Password,base,from.getId());
551         trans.checkpoint(to.id, Env.ALWAYS);
552
553         return Result.ok(to);
554     }
555     
556     @Override
557     public Result<Users> cred(List<CredDAO.Data> from, Users to) {
558         List<User> cu = to.getUser();
559         for (CredDAO.Data cred : from) {
560             User user = new User();
561             user.setId(cred.id);
562             user.setExpires(Chrono.timeStamp(cred.expires));
563             user.setType(cred.type);
564             user.setTag(cred.tag);
565             cu.add(user);
566         }
567         return Result.ok(to);
568     }
569     
570     @Override
571     public Result<Certs> cert(List<CertDAO.Data> from, Certs to) {
572         List<Cert> lc = to.getCert();
573         for (CertDAO.Data fcred : from) {
574             Cert cert = new Cert();
575             cert.setId(fcred.id);
576             cert.setX500(fcred.x500);
577             /**TODO - change Interface 
578              * @deprecated */
579             cert.setFingerprint(fcred.serial.toByteArray());
580             lc.add(cert);
581         }
582         return Result.ok(to);
583     }
584
585     /**
586      * Analyze whether Requests should be acted on now, or in the future, based on Start Date, and whether the requester
587      * is allowed to change this value directly
588      * 
589      * Returning Result.OK means it should be done in the future.
590      * Returning Result.ACC_Now means to act on table change now.
591      */
592     @Override
593     public Result<FutureDAO.Data> future(AuthzTrans trans, String table, Request from, 
594                 Bytification content, boolean enableApproval,  Memo memo, MayChange mc) {
595         Result<?> rMayChange;
596         boolean needsAppr = enableApproval?trans.requested(REQD_TYPE.future):false; 
597         if (!needsAppr && (needsAppr = (rMayChange=mc.mayChange()).notOK())) {
598             if (enableApproval) {
599                 if (!trans.requested(AuthzTrans.REQD_TYPE.future)) {
600                     return Result.err(rMayChange);
601                 }
602             } else {
603                 return Result.err(rMayChange);
604             }
605         }
606         GregorianCalendar now = new GregorianCalendar(); 
607         GregorianCalendar start = from.getStart()==null?now:from.getStart().toGregorianCalendar();
608         
609         GregorianCalendar expires = trans.org().expiration(start, Expiration.Future);
610         XMLGregorianCalendar xgc;
611         if ((xgc=from.getEnd())!=null) {
612             GregorianCalendar fgc = xgc.toGregorianCalendar();
613             expires = expires.before(fgc)?expires:fgc; // Min of desired expiration, and Org expiration
614         }
615         
616         //TODO needs two answers from this.  What's the NSS, and may Change.
617         FutureDAO.Data fto;
618         if (start.after(now) || needsAppr ) {
619             //String user = trans.user();
620             fto = new FutureDAO.Data();
621             fto.target=table;
622             fto.memo = memo.get();
623             fto.start = start.getTime();
624             fto.expires = expires.getTime();
625             if (needsAppr) { // Need to add Approvers...
626                 /*
627                 Result<Data> rslt = mc.getNsd();
628                 if (rslt.notOKorIsEmpty())return Result.err(rslt);
629                 appr.addAll(mc.getNsd().value.responsible);
630                 try {
631                     //Note from 2013 Is this getting Approvers for user only?  What about Delegates?
632                     // 3/25/2014.  Approvers are set by Corporate policy.  We don't have to worry here about what that means.
633                     // It is important to get Delegates, if necessary, at notification time
634                     // If we add delegates now, it will get all confused as to who is actually responsible.
635                     for (Organization.User ou : org.getApprovers(trans, user)) {
636                         appr.add(ou.email);
637                     }
638                 } catch (Exception e) {
639                     return Result.err(Status.ERR_Policy,org.getName() + " did not respond with Approvers: " + e.getLocalizedMessage());
640                 }
641                 */
642             }
643             try {
644                 fto.construct = content.bytify();
645             } catch (Exception e) {
646                 return Result.err(Status.ERR_BadData,"Data cannot be saved for Future.");
647             }
648         } else {
649             return Result.err(Status.ACC_Now, "Make Data changes now.");
650         }
651         return Result.ok(fto);
652     }
653
654
655     /* (non-Javadoc)
656      * @see org.onap.aaf.auth.service.mapper.Mapper#history(java.util.List)
657      */
658     @Override
659     public Result<History> history(AuthzTrans trans, List<HistoryDAO.Data> history, final int sort) {
660         History hist = new History();
661         List<Item> items = hist.getItem();
662         for (HistoryDAO.Data data : history) {
663             History.Item item = new History.Item();
664             item.setYYYYMM(Integer.toString(data.yr_mon));
665             Date date = Chrono.uuidToDate(data.id);
666             item.setTimestamp(Chrono.timeStamp(date));
667             item.setAction(data.action);
668             item.setMemo(data.memo);
669             item.setSubject(data.subject);
670             item.setTarget(data.target);
671             item.setUser(data.user);
672             items.add(item);
673         }
674         
675         if (sort != 0) {
676             TimeTaken tt = trans.start("Sort ", Env.SUB);
677             try {
678                 java.util.Collections.sort(items, new Comparator<Item>() {
679                     @Override
680                     public int compare(Item o1, Item o2) {
681                         return sort*(o1.getTimestamp().compare(o2.getTimestamp()));
682                     }
683                 });
684             } finally {
685                 tt.done();
686             }
687         }
688         return Result.ok(hist);
689     }
690
691     @Override
692     public Error errorFromMessage(StringBuilder holder, String msgID, String text, String... var) {
693         Error err = new Error();
694         err.setMessageId(msgID);
695         // AT&T Restful Error Format requires numbers "%" placements
696         err.setText(Vars.convert(holder, text, (Object[])var));
697         for (String s : var) {
698             err.getVariables().add(s);
699         }
700         return err;
701     }
702     
703     @Override
704     public Class<?> getClass(API api) {
705         switch(api) {
706             case NSS:  return Nss.class;
707             case NS_REQ: return NsRequest.class;
708             case PERMS: return Perms.class;
709             case PERM_KEY: return PermKey.class;
710             case ROLES: return Roles.class;
711             case ROLE: return Role.class;
712             case USERS: return Users.class;
713             case DELGS: return Delgs.class;
714             case CERTS: return Certs.class;
715             case DELG_REQ: return DelgRequest.class;
716             case PERM_REQ: return PermRequest.class;
717             case ROLE_REQ:  return RoleRequest.class;
718             case CRED_REQ:  return CredRequest.class;
719             case USER_ROLE_REQ:  return UserRoleRequest.class;
720             case USER_ROLES: return UserRoles.class;
721             case ROLE_PERM_REQ:  return RolePermRequest.class;
722             case APPROVALS: return Approvals.class;
723             case KEYS: return Keys.class;
724             case HISTORY: return History.class;
725 //            case MODEL: return Model.class;
726             case ERROR: return Error.class;
727             case API: return Api.class;
728             case VOID: return Void.class;
729         }
730         return null;
731     }
732
733     @SuppressWarnings("unchecked")
734     @Override
735     public <A> A newInstance(API api) {
736         switch(api) {
737             case NS_REQ: return (A) new NsRequest();
738             case NSS: return (A) new Nss();
739             case PERMS: return (A)new Perms();
740             case PERM_KEY: return (A)new PermKey();
741             case ROLES: return (A)new Roles();
742             case ROLE: return (A)new Role();
743             case USERS: return (A)new Users();
744             case DELGS: return (A)new Delgs();
745             case CERTS: return (A)new Certs();
746             case PERM_REQ: return (A)new PermRequest();
747             case CRED_REQ: return (A)new CredRequest();
748             case ROLE_REQ:  return (A)new RoleRequest();
749             case USER_ROLE_REQ:  return (A)new UserRoleRequest();
750             case USER_ROLES:  return (A)new UserRoles();
751             case ROLE_PERM_REQ:  return (A)new RolePermRequest();
752             case HISTORY: return (A)new History();
753             case KEYS: return (A)new Keys();
754             //case MODEL: return (A)new Model();
755             case ERROR: return (A)new Error();
756             case API: return (A)new Api();
757             case VOID: return null;
758             
759             case APPROVALS:    return (A) new Approvals();
760             case DELG_REQ: return (A) new DelgRequest();
761         }
762         return null;
763     }
764     
765     @SuppressWarnings("unchecked")
766     /**
767      * Get Typed Marshaler as they are defined
768      * 
769      * @param api
770      * @return
771      */
772     public <A> Marshal<A> getMarshal(API api) {
773         switch(api) {
774             case CERTS: return (Marshal<A>) new CertsMarshal();
775             default:
776                 return null;
777         }
778     }
779
780     @Override
781     public Result<Approvals> approvals(List<ApprovalDAO.Data> lAppr) {
782         Approvals apprs = new Approvals();
783         List<Approval> lappr = apprs.getApprovals();
784         Approval a;
785         for (ApprovalDAO.Data appr : lAppr) {
786             a = new Approval();
787             a.setId(appr.id.toString());
788             if (appr.ticket==null) {
789                 a.setTicket(null);
790             } else {
791                 a.setTicket(appr.ticket.toString());
792             }
793             a.setUser(appr.user);
794             a.setApprover(appr.approver);
795             a.setType(appr.type);
796             a.setStatus(appr.status);
797             a.setMemo(appr.memo);
798             a.setOperation(appr.operation);
799             a.setUpdated(Chrono.timeStamp(appr.updated));
800             lappr.add(a);
801         }
802         return Result.ok(apprs);
803     }
804     
805     @Override
806     public Result<List<ApprovalDAO.Data>> approvals(Approvals apprs) {
807         List<ApprovalDAO.Data>  lappr = new ArrayList<>();
808         for (Approval a : apprs.getApprovals()) {
809             ApprovalDAO.Data ad = new ApprovalDAO.Data();
810             String str = a.getId();
811             if (str!=null)ad.id=UUID.fromString(str);
812             str = a.getTicket();
813             if (str!=null)ad.ticket=UUID.fromString(str);
814             ad.user=a.getUser();
815             ad.approver=a.getApprover();
816             ad.type=a.getType();
817             ad.status=a.getStatus();
818             ad.operation=a.getOperation();
819             ad.memo=a.getMemo();
820             
821             XMLGregorianCalendar xgc = a.getUpdated();
822             if (xgc!=null)ad.updated=xgc.toGregorianCalendar().getTime();
823             lappr.add(ad);
824         }
825         return Result.ok(lappr);
826     }
827
828     @Override
829     public Result<Delgs> delegate(List<DelegateDAO.Data> lDelg) {
830         Delgs delgs = new Delgs();
831         List<Delg> ldelg = delgs.getDelgs();
832         Delg d;
833         for (DelegateDAO.Data del: lDelg) {
834             d = new Delg();
835             d.setUser(del.user);
836             d.setDelegate(del.delegate);
837             if (del.expires!=null)d.setExpires(Chrono.timeStamp(del.expires));
838             ldelg.add(d);
839         }
840         return Result.ok(delgs);
841     }
842
843     @Override
844     public Result<Data> delegate(AuthzTrans trans, Request base) {
845         try {
846             DelgRequest from = (DelgRequest)base;
847             DelegateDAO.Data to = new DelegateDAO.Data();
848             String user = from.getUser();
849             to.user = user;
850             String delegate = from.getDelegate();
851             to.delegate = delegate;
852             to.expires = getExpires(trans.org(),Expiration.UserDelegate,base,from.getUser());
853             trans.checkpoint(to.user+"=>"+to.delegate, Env.ALWAYS);
854
855             return Result.ok(to);
856         } catch (Exception t) {
857             return Result.err(Status.ERR_BadData,t.getMessage());
858         }
859     }
860
861     /*
862      * We want "Expired" dates to start at a specified time set by the Organization, and consistent wherever
863      * the date is created from.
864      */ 
865     private Date getExpires(Organization org, Expiration exp, Request base, String id) {
866         XMLGregorianCalendar end = base.getEnd();
867         GregorianCalendar gc = end==null?new GregorianCalendar():end.toGregorianCalendar();
868         GregorianCalendar orggc;
869         orggc = org.expiration(gc,exp,id); 
870
871         // We'll choose the lesser of dates to ensure Policy Compliance...
872     
873         GregorianCalendar endgc = end==null||gc.after(orggc)?orggc:gc;
874         // Allow the Organization to determine when official "day Start" begins, Specifically when to consider something Expired.
875         endgc = Chrono.firstMomentOfDay(endgc);
876         endgc.set(GregorianCalendar.HOUR_OF_DAY, org.startOfDay());
877         return endgc.getTime();
878     }
879
880
881     @Override
882     public Result<Keys> keys(Collection<String> from) {
883         Keys keys = new Keys();
884         keys.getKey().addAll(from);
885         return Result.ok(keys).emptyList(from.isEmpty());
886     }
887
888 }