View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.backend.jpa.access;
20  
21  import java.sql.Timestamp;
22  import java.text.DateFormat;
23  import java.text.SimpleDateFormat;
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.stream.Collectors;
28  
29  import org.apache.logging.log4j.LogManager;
30  import org.apache.logging.log4j.Logger;
31  import org.mycore.access.MCRAccessManager;
32  import org.mycore.access.mcrimpl.MCRAccessStore;
33  import org.mycore.access.mcrimpl.MCRRuleMapping;
34  import org.mycore.backend.jpa.MCREntityManagerProvider;
35  
36  import jakarta.persistence.EntityManager;
37  import jakarta.persistence.NoResultException;
38  import jakarta.persistence.TypedQuery;
39  import jakarta.persistence.criteria.CriteriaBuilder;
40  import jakarta.persistence.criteria.CriteriaQuery;
41  import jakarta.persistence.criteria.Path;
42  import jakarta.persistence.criteria.Root;
43  
44  /**
45   * JPA implementation of acceess store to manage access rights
46   * 
47   * @author Arne Seifert
48   * @author Thomas Scheffler (yagee)
49   * 
50   */
51  public class MCRJPAAccessStore extends MCRAccessStore {
52      private final DateFormat dateFormat = new SimpleDateFormat(SQL_DATEFORMAT, Locale.ROOT);
53  
54      private static final Logger LOGGER = LogManager.getLogger();
55  
56      @Override
57      public String getRuleID(String objID, String acPool) {
58  
59          EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
60          CriteriaBuilder cb = em.getCriteriaBuilder();
61          CriteriaQuery<String> query = cb.createQuery(String.class);
62          Root<MCRACCESS> ac = query.from(MCRACCESS.class);
63          try {
64              return em.createQuery(
65                  query.select(ac.get(MCRACCESS_.rule).get(MCRACCESSRULE_.rid))
66                      .where(cb.equal(ac.get(MCRACCESS_.key).get(MCRACCESSPK_.objid), objID),
67                          cb.equal(ac.get(MCRACCESS_.key).get(MCRACCESSPK_.acpool), acPool)))
68                  .getSingleResult();
69          } catch (NoResultException e) {
70              return null;
71          }
72      }
73  
74      /**
75       * method creates a new AccessDefinition in db
76       * 
77       * @param rulemapping
78       *            with values
79       */
80      @Override
81      public void createAccessDefinition(MCRRuleMapping rulemapping) {
82  
83          if (!existAccessDefinition(rulemapping.getPool(), rulemapping.getObjId())) {
84              EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
85              MCRACCESSRULE accessRule = getAccessRule(rulemapping.getRuleId());
86              if (accessRule == null) {
87                  throw new NullPointerException("Cannot map a null rule.");
88              }
89              MCRACCESS accdef = new MCRACCESS();
90  
91              accdef.setKey(new MCRACCESSPK(rulemapping.getPool(), rulemapping.getObjId()));
92              accdef.setRule(accessRule);
93              accdef.setCreator(rulemapping.getCreator());
94              accdef.setCreationdate(Timestamp.valueOf(dateFormat.format(rulemapping.getCreationdate())));
95              em.persist(accdef);
96          }
97      }
98  
99      /**
100      * internal helper method to check existance of object
101      */
102     private boolean existAccessDefinition(String pool, String objid) {
103         MCRACCESSPK key = new MCRACCESSPK(pool, objid);
104         return MCREntityManagerProvider.getCurrentEntityManager().find(MCRACCESS.class, key) != null;
105     }
106 
107     @Override
108     public boolean existsRule(String objid, String pool) {
109         if (objid == null || objid.equals("")) {
110             LOGGER.warn("empty parameter objid in existsRule");
111             return false;
112         }
113         try {
114             return getRuleID(objid, pool) != null;
115         } catch (NoResultException e) {
116             return false;
117         }
118     }
119 
120     /**
121      * delete given definition in db
122      * 
123      * @param rulemapping
124      *            rule to be deleted
125      */
126     @Override
127     public void deleteAccessDefinition(MCRRuleMapping rulemapping) {
128         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
129         em.createQuery(
130             "delete MCRACCESS " + "where ACPOOL = '" + rulemapping.getPool() + "'" + " AND OBJID = '"
131                 + rulemapping.getObjId() + "'")
132             .executeUpdate();
133         MCRAccessManager.invalidAllPermissionCachesById(rulemapping.getObjId());
134     }
135 
136     /**
137      * update AccessDefinition in db for given MCRAccessData
138      */
139     @Override
140     public void updateAccessDefinition(MCRRuleMapping rulemapping) {
141         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
142         MCRACCESSRULE accessRule = getAccessRule(rulemapping.getRuleId());
143         if (accessRule == null) {
144             throw new NullPointerException("Cannot map a null rule.");
145         }
146         // update
147         MCRACCESS accdef = em.find(MCRACCESS.class,
148             new MCRACCESSPK(rulemapping.getPool(), rulemapping.getObjId()));
149         accdef.setRule(accessRule);
150         accdef.setCreator(rulemapping.getCreator());
151         accdef.setCreationdate(Timestamp.valueOf(dateFormat.format(rulemapping.getCreationdate())));
152         MCRAccessManager.invalidAllPermissionCachesById(rulemapping.getObjId());
153     }
154 
155     /**
156      * method returns AccessDefinition for given key values
157      * 
158      * @param pool
159      *            name of accesspool
160      * @param objid
161      *            objectid of MCRObject
162      * @return MCRAccessData
163      */
164     @Override
165     public MCRRuleMapping getAccessDefinition(String pool, String objid) {
166         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
167         CriteriaBuilder cb = em.getCriteriaBuilder();
168         CriteriaQuery<MCRACCESS> query = cb.createQuery(MCRACCESS.class);
169         Root<MCRACCESS> root = query.from(MCRACCESS.class);
170         MCRRuleMapping rulemapping = new MCRRuleMapping();
171         try {
172             MCRACCESS data = em
173                 .createQuery(query.where(cb.equal(root.get(MCRACCESS_.key), new MCRACCESSPK(pool, objid))))
174                 .getSingleResult();
175             rulemapping.setCreationdate(data.getCreationdate());
176             rulemapping.setCreator(data.getCreator());
177             rulemapping.setObjId(data.getKey().getObjid());
178             rulemapping.setPool(data.getKey().getAcpool());
179             rulemapping.setRuleId(data.getRule().getRid());
180             em.detach(data);
181         } catch (NoResultException e) {
182             //returning empty rulemapping is fine
183         }
184         return rulemapping;
185     }
186 
187     @Override
188     public ArrayList<String> getMappedObjectId(String pool) {
189 
190         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
191         List<MCRACCESS> l = em.createQuery("from MCRACCESS where ACPOOL = '" + pool + "'", MCRACCESS.class)
192             .getResultList();
193         return l.stream()
194             .map(aL -> aL.getKey().getObjid())
195             .collect(Collectors.toCollection(ArrayList::new));
196     }
197 
198     @Override
199     public ArrayList<String> getPoolsForObject(String objid) {
200 
201         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
202         List<MCRACCESS> l = em.createQuery("from MCRACCESS where OBJID = '" + objid + "'", MCRACCESS.class)
203             .getResultList();
204         return l.stream()
205             .map(access -> access.getKey().getAcpool())
206             .collect(Collectors.toCollection(ArrayList::new));
207     }
208 
209     @Override
210     public ArrayList<String> getDatabasePools() {
211         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
212         CriteriaQuery<MCRACCESS> query = em.getCriteriaBuilder().createQuery(MCRACCESS.class);
213         return em.createQuery(query.select(query.from(MCRACCESS.class)))
214             .getResultList()
215             .stream()
216             .map(MCRACCESS::getKey)
217             .map(MCRACCESSPK::getAcpool)
218             .distinct()
219             .collect(Collectors.toCollection(ArrayList::new));
220     }
221 
222     @Override
223     public List<String> getDistinctStringIDs() {
224         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
225         CriteriaBuilder cb = em.getCriteriaBuilder();
226         CriteriaQuery<String> query = cb.createQuery(String.class);
227         Path<String> selection = query.from(MCRACCESS.class).get(MCRACCESS_.key).get(MCRACCESSPK_.objid);
228         return em.createQuery(query.select(selection).distinct(true).orderBy(cb.asc(selection))).getResultList();
229     }
230 
231     /**
232      * Checks if a rule mappings uses the rule.
233      * 
234      * @param ruleid the rule id to check
235      * @return true if the rule exists and is used, otherwise false
236      */
237     @Override
238     public boolean isRuleInUse(String ruleid) {
239         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
240         TypedQuery<MCRACCESS> query = em
241             .createQuery("from MCRACCESS as accdef where accdef.rule.rid = '" + ruleid + "'", MCRACCESS.class);
242         return !query.getResultList().isEmpty();
243     }
244 
245     private static MCRACCESSRULE getAccessRule(String rid) {
246         EntityManager em = MCREntityManagerProvider.getCurrentEntityManager();
247         return em.find(MCRACCESSRULE.class, rid);
248     }
249 }