Remove Tabs, per Jococo
[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.DelegateDAO.Data;
42 import org.onap.aaf.auth.dao.cass.FutureDAO;
43 import org.onap.aaf.auth.dao.cass.HistoryDAO;
44 import org.onap.aaf.auth.dao.cass.Namespace;
45 import org.onap.aaf.auth.dao.cass.NsSplit;
46 import org.onap.aaf.auth.dao.cass.NsType;
47 import org.onap.aaf.auth.dao.cass.PermDAO;
48 import org.onap.aaf.auth.dao.cass.RoleDAO;
49 import org.onap.aaf.auth.dao.cass.Status;
50 import org.onap.aaf.auth.dao.cass.UserRoleDAO;
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             }
538             if (passwd != null) {
539                 to.cred = ByteBuffer.wrap(passwd.getBytes());
540                 to.type = CredDAO.RAW; 
541             } else {
542                 to.type = CredDAO.NONE;
543             }
544         }
545             
546         // Note: Ensure requested EndDate created will match Organization Password Rules
547         //  P.S. Do not apply TempPassword rule here. Do that when you know you are doing a Create/Reset (see Service)
548         to.expires = getExpires(trans.org(),Expiration.Password,base,from.getId());
549         trans.checkpoint(to.id, Env.ALWAYS);
550
551         return Result.ok(to);
552     }
553     
554     @Override
555     public Result<Users> cred(List<CredDAO.Data> from, Users to) {
556         List<User> cu = to.getUser();
557         for (CredDAO.Data cred : from) {
558             User user = new User();
559             user.setId(cred.id);
560             user.setExpires(Chrono.timeStamp(cred.expires));
561             user.setType(cred.type);
562             user.setTag(cred.tag);
563             cu.add(user);
564         }
565         return Result.ok(to);
566     }
567     
568     @Override
569     public Result<Certs> cert(List<CertDAO.Data> from, Certs to) {
570         List<Cert> lc = to.getCert();
571         for (CertDAO.Data fcred : from) {
572             Cert cert = new Cert();
573             cert.setId(fcred.id);
574             cert.setX500(fcred.x500);
575             /**TODO - change Interface 
576              * @deprecated */
577             cert.setFingerprint(fcred.serial.toByteArray());
578             lc.add(cert);
579         }
580         return Result.ok(to);
581     }
582
583     /**
584      * Analyze whether Requests should be acted on now, or in the future, based on Start Date, and whether the requester
585      * is allowed to change this value directly
586      * 
587      * Returning Result.OK means it should be done in the future.
588      * Returning Result.ACC_Now means to act on table change now.
589      */
590     @Override
591     public Result<FutureDAO.Data> future(AuthzTrans trans, String table, Request from, 
592                 Bytification content, boolean enableApproval,  Memo memo, MayChange mc) {
593         Result<?> rMayChange;
594         boolean needsAppr = enableApproval?trans.requested(REQD_TYPE.future):false; 
595         if (!needsAppr && (needsAppr = (rMayChange=mc.mayChange()).notOK())) {
596             if (enableApproval) {
597                 if (!trans.requested(AuthzTrans.REQD_TYPE.future)) {
598                     return Result.err(rMayChange);
599                 }
600             } else {
601                 return Result.err(rMayChange);
602             }
603         }
604         GregorianCalendar now = new GregorianCalendar(); 
605         GregorianCalendar start = from.getStart()==null?now:from.getStart().toGregorianCalendar();
606         
607         GregorianCalendar expires = trans.org().expiration(start, Expiration.Future);
608         XMLGregorianCalendar xgc;
609         if ((xgc=from.getEnd())!=null) {
610             GregorianCalendar fgc = xgc.toGregorianCalendar();
611             expires = expires.before(fgc)?expires:fgc; // Min of desired expiration, and Org expiration
612         }
613         
614         //TODO needs two answers from this.  What's the NSS, and may Change.
615         FutureDAO.Data fto;
616         if (start.after(now) || needsAppr ) {
617             //String user = trans.user();
618             fto = new FutureDAO.Data();
619             fto.target=table;
620             fto.memo = memo.get();
621             fto.start = start.getTime();
622             fto.expires = expires.getTime();
623             if (needsAppr) { // Need to add Approvers...
624                 /*
625                 Result<Data> rslt = mc.getNsd();
626                 if (rslt.notOKorIsEmpty())return Result.err(rslt);
627                 appr.addAll(mc.getNsd().value.responsible);
628                 try {
629                     //Note from 2013 Is this getting Approvers for user only?  What about Delegates?
630                     // 3/25/2014.  Approvers are set by Corporate policy.  We don't have to worry here about what that means.
631                     // It is important to get Delegates, if necessary, at notification time
632                     // If we add delegates now, it will get all confused as to who is actually responsible.
633                     for (Organization.User ou : org.getApprovers(trans, user)) {
634                         appr.add(ou.email);
635                     }
636                 } catch (Exception e) {
637                     return Result.err(Status.ERR_Policy,org.getName() + " did not respond with Approvers: " + e.getLocalizedMessage());
638                 }
639                 */
640             }
641             try {
642                 fto.construct = content.bytify();
643             } catch (Exception e) {
644                 return Result.err(Status.ERR_BadData,"Data cannot be saved for Future.");
645             }
646         } else {
647             return Result.err(Status.ACC_Now, "Make Data changes now.");
648         }
649         return Result.ok(fto);
650     }
651
652
653     /* (non-Javadoc)
654      * @see org.onap.aaf.auth.service.mapper.Mapper#history(java.util.List)
655      */
656     @Override
657     public Result<History> history(AuthzTrans trans, List<HistoryDAO.Data> history, final int sort) {
658         History hist = new History();
659         List<Item> items = hist.getItem();
660         for (HistoryDAO.Data data : history) {
661             History.Item item = new History.Item();
662             item.setYYYYMM(Integer.toString(data.yr_mon));
663             Date date = Chrono.uuidToDate(data.id);
664             item.setTimestamp(Chrono.timeStamp(date));
665             item.setAction(data.action);
666             item.setMemo(data.memo);
667             item.setSubject(data.subject);
668             item.setTarget(data.target);
669             item.setUser(data.user);
670             items.add(item);
671         }
672         
673         if (sort != 0) {
674             TimeTaken tt = trans.start("Sort ", Env.SUB);
675             try {
676                 java.util.Collections.sort(items, new Comparator<Item>() {
677                     @Override
678                     public int compare(Item o1, Item o2) {
679                         return sort*(o1.getTimestamp().compare(o2.getTimestamp()));
680                     }
681                 });
682             } finally {
683                 tt.done();
684             }
685         }
686         return Result.ok(hist);
687     }
688
689     @Override
690     public Error errorFromMessage(StringBuilder holder, String msgID, String text, String... var) {
691         Error err = new Error();
692         err.setMessageId(msgID);
693         // AT&T Restful Error Format requires numbers "%" placements
694         err.setText(Vars.convert(holder, text, (Object[])var));
695         for (String s : var) {
696             err.getVariables().add(s);
697         }
698         return err;
699     }
700     
701     @Override
702     public Class<?> getClass(API api) {
703         switch(api) {
704             case NSS:  return Nss.class;
705             case NS_REQ: return NsRequest.class;
706             case PERMS: return Perms.class;
707             case PERM_KEY: return PermKey.class;
708             case ROLES: return Roles.class;
709             case ROLE: return Role.class;
710             case USERS: return Users.class;
711             case DELGS: return Delgs.class;
712             case CERTS: return Certs.class;
713             case DELG_REQ: return DelgRequest.class;
714             case PERM_REQ: return PermRequest.class;
715             case ROLE_REQ:  return RoleRequest.class;
716             case CRED_REQ:  return CredRequest.class;
717             case USER_ROLE_REQ:  return UserRoleRequest.class;
718             case USER_ROLES: return UserRoles.class;
719             case ROLE_PERM_REQ:  return RolePermRequest.class;
720             case APPROVALS: return Approvals.class;
721             case KEYS: return Keys.class;
722             case HISTORY: return History.class;
723 //            case MODEL: return Model.class;
724             case ERROR: return Error.class;
725             case API: return Api.class;
726             case VOID: return Void.class;
727         }
728         return null;
729     }
730
731     @SuppressWarnings("unchecked")
732     @Override
733     public <A> A newInstance(API api) {
734         switch(api) {
735             case NS_REQ: return (A) new NsRequest();
736             case NSS: return (A) new Nss();
737             case PERMS: return (A)new Perms();
738             case PERM_KEY: return (A)new PermKey();
739             case ROLES: return (A)new Roles();
740             case ROLE: return (A)new Role();
741             case USERS: return (A)new Users();
742             case DELGS: return (A)new Delgs();
743             case CERTS: return (A)new Certs();
744             case PERM_REQ: return (A)new PermRequest();
745             case CRED_REQ: return (A)new CredRequest();
746             case ROLE_REQ:  return (A)new RoleRequest();
747             case USER_ROLE_REQ:  return (A)new UserRoleRequest();
748             case USER_ROLES:  return (A)new UserRoles();
749             case ROLE_PERM_REQ:  return (A)new RolePermRequest();
750             case HISTORY: return (A)new History();
751             case KEYS: return (A)new Keys();
752             //case MODEL: return (A)new Model();
753             case ERROR: return (A)new Error();
754             case API: return (A)new Api();
755             case VOID: return null;
756             
757             case APPROVALS:    return (A) new Approvals();
758             case DELG_REQ: return (A) new DelgRequest();
759         }
760         return null;
761     }
762     
763     @SuppressWarnings("unchecked")
764     /**
765      * Get Typed Marshaler as they are defined
766      * 
767      * @param api
768      * @return
769      */
770     public <A> Marshal<A> getMarshal(API api) {
771         switch(api) {
772             case CERTS: return (Marshal<A>) new CertsMarshal();
773             default:
774                 return null;
775         }
776     }
777
778     @Override
779     public Result<Approvals> approvals(List<ApprovalDAO.Data> lAppr) {
780         Approvals apprs = new Approvals();
781         List<Approval> lappr = apprs.getApprovals();
782         Approval a;
783         for (ApprovalDAO.Data appr : lAppr) {
784             a = new Approval();
785             a.setId(appr.id.toString());
786             if (appr.ticket==null) {
787                 a.setTicket(null);
788             } else {
789                 a.setTicket(appr.ticket.toString());
790             }
791             a.setUser(appr.user);
792             a.setApprover(appr.approver);
793             a.setType(appr.type);
794             a.setStatus(appr.status);
795             a.setMemo(appr.memo);
796             a.setOperation(appr.operation);
797             a.setUpdated(Chrono.timeStamp(appr.updated));
798             lappr.add(a);
799         }
800         return Result.ok(apprs);
801     }
802     
803     @Override
804     public Result<List<ApprovalDAO.Data>> approvals(Approvals apprs) {
805         List<ApprovalDAO.Data>  lappr = new ArrayList<>();
806         for (Approval a : apprs.getApprovals()) {
807             ApprovalDAO.Data ad = new ApprovalDAO.Data();
808             String str = a.getId();
809             if (str!=null)ad.id=UUID.fromString(str);
810             str = a.getTicket();
811             if (str!=null)ad.ticket=UUID.fromString(str);
812             ad.user=a.getUser();
813             ad.approver=a.getApprover();
814             ad.type=a.getType();
815             ad.status=a.getStatus();
816             ad.operation=a.getOperation();
817             ad.memo=a.getMemo();
818             
819             XMLGregorianCalendar xgc = a.getUpdated();
820             if (xgc!=null)ad.updated=xgc.toGregorianCalendar().getTime();
821             lappr.add(ad);
822         }
823         return Result.ok(lappr);
824     }
825
826     @Override
827     public Result<Delgs> delegate(List<DelegateDAO.Data> lDelg) {
828         Delgs delgs = new Delgs();
829         List<Delg> ldelg = delgs.getDelgs();
830         Delg d;
831         for (DelegateDAO.Data del: lDelg) {
832             d = new Delg();
833             d.setUser(del.user);
834             d.setDelegate(del.delegate);
835             if (del.expires!=null)d.setExpires(Chrono.timeStamp(del.expires));
836             ldelg.add(d);
837         }
838         return Result.ok(delgs);
839     }
840
841     @Override
842     public Result<Data> delegate(AuthzTrans trans, Request base) {
843         try {
844             DelgRequest from = (DelgRequest)base;
845             DelegateDAO.Data to = new DelegateDAO.Data();
846             String user = from.getUser();
847             to.user = user;
848             String delegate = from.getDelegate();
849             to.delegate = delegate;
850             to.expires = getExpires(trans.org(),Expiration.UserDelegate,base,from.getUser());
851             trans.checkpoint(to.user+"=>"+to.delegate, Env.ALWAYS);
852
853             return Result.ok(to);
854         } catch (Exception t) {
855             return Result.err(Status.ERR_BadData,t.getMessage());
856         }
857     }
858
859     /*
860      * We want "Expired" dates to start at a specified time set by the Organization, and consistent wherever
861      * the date is created from.
862      */ 
863     private Date getExpires(Organization org, Expiration exp, Request base, String id) {
864         XMLGregorianCalendar end = base.getEnd();
865         GregorianCalendar gc = end==null?new GregorianCalendar():end.toGregorianCalendar();
866         GregorianCalendar orggc;
867         orggc = org.expiration(gc,exp,id); 
868
869         // We'll choose the lesser of dates to ensure Policy Compliance...
870     
871         GregorianCalendar endgc = end==null||gc.after(orggc)?orggc:gc;
872         // Allow the Organization to determine when official "day Start" begins, Specifically when to consider something Expired.
873         endgc = Chrono.firstMomentOfDay(endgc);
874         endgc.set(GregorianCalendar.HOUR_OF_DAY, org.startOfDay());
875         return endgc.getTime();
876     }
877
878
879     @Override
880     public Result<Keys> keys(Collection<String> from) {
881         Keys keys = new Keys();
882         keys.getKey().addAll(from);
883         return Result.ok(keys).emptyList(from.isEmpty());
884     }
885
886 }