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.frontend.acl2.resources;
20  
21  import java.io.InputStream;
22  import java.util.Collection;
23  import java.util.Date;
24  
25  import org.jdom2.Document;
26  import org.jdom2.Element;
27  import org.jdom2.input.SAXBuilder;
28  import org.jdom2.xpath.XPathExpression;
29  import org.jdom2.xpath.XPathFactory;
30  import org.mycore.access.mcrimpl.MCRAccessRule;
31  import org.mycore.access.mcrimpl.MCRAccessStore;
32  import org.mycore.access.mcrimpl.MCRRuleMapping;
33  import org.mycore.access.mcrimpl.MCRRuleStore;
34  import org.mycore.common.MCRSession;
35  import org.mycore.common.MCRSessionMgr;
36  import org.mycore.common.config.MCRConfiguration2;
37  import org.mycore.common.content.MCRContent;
38  import org.mycore.frontend.MCRFrontendUtil;
39  import org.mycore.frontend.jersey.MCRJerseyUtil;
40  import org.mycore.frontend.jersey.filter.access.MCRRestrictedAccess;
41  
42  import com.google.gson.JsonArray;
43  import com.google.gson.JsonObject;
44  import com.google.gson.JsonParser;
45  
46  import jakarta.servlet.ServletContext;
47  import jakarta.servlet.http.HttpServletRequest;
48  import jakarta.servlet.http.HttpServletResponse;
49  import jakarta.ws.rs.Consumes;
50  import jakarta.ws.rs.DELETE;
51  import jakarta.ws.rs.GET;
52  import jakarta.ws.rs.POST;
53  import jakarta.ws.rs.PUT;
54  import jakarta.ws.rs.Path;
55  import jakarta.ws.rs.Produces;
56  import jakarta.ws.rs.WebApplicationException;
57  import jakarta.ws.rs.core.Context;
58  import jakarta.ws.rs.core.MediaType;
59  import jakarta.ws.rs.core.Response;
60  import jakarta.ws.rs.core.Response.Status;
61  
62  @Path("ACLE")
63  public class MCRAclEditorResource {
64  
65      private static final MCRRuleStore RULE_STORE = MCRRuleStore.getInstance();
66  
67      private static final MCRAccessStore ACCESS_STORE = MCRAccessStore.getInstance();
68  
69      private static final String JSON_ACCESSID = "accessID";
70  
71      private static final String JSON_ACCESSPOOL = "accessPool";
72  
73      private static final String JSON_RULE = "rule";
74  
75      private static final String JSON_SUCCESS = "success";
76  
77      @Context
78      HttpServletRequest request;
79  
80      @Context
81      HttpServletResponse response;
82  
83      @Context
84      ServletContext context;
85  
86      @GET
87      @Path("start")
88      @MCRRestrictedAccess(MCRAclEditorPermission.class)
89      @Produces(MediaType.TEXT_HTML)
90      public InputStream start() throws Exception {
91          return transform("/META-INF/resources/modules/acl-editor2/gui/xml/webpage.xml");
92      }
93  
94      protected InputStream transform(String xmlFile) throws Exception {
95          InputStream guiXML = getClass().getResourceAsStream(xmlFile);
96          if (guiXML == null) {
97              throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).build());
98          }
99          SAXBuilder saxBuilder = new SAXBuilder();
100         Document webPage = saxBuilder.build(guiXML);
101         XPathExpression<Object> xpath = XPathFactory.instance().compile(
102             "/MyCoReWebPage/section/div[@id='mycore-acl-editor2']");
103         Object node = xpath.evaluateFirst(webPage);
104         MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
105         String lang = mcrSession.getCurrentLanguage();
106         if (node != null) {
107             Element mainDiv = (Element) node;
108             mainDiv.setAttribute("lang", lang);
109             String bsPath = MCRConfiguration2.getString("MCR.bootstrap.path").orElse("");
110             if (!"".equals(bsPath)) {
111                 bsPath = MCRFrontendUtil.getBaseURL() + bsPath;
112                 Element item = new Element("link").setAttribute("href", bsPath).setAttribute("rel", "stylesheet")
113                     .setAttribute("type", "text/css");
114                 mainDiv.addContent(0, item);
115             }
116         }
117         MCRContent content = MCRJerseyUtil.transform(webPage, request);
118         return content.getInputStream();
119     }
120 
121     @GET
122     @MCRRestrictedAccess(MCRAclEditorPermission.class)
123     public String list() {
124         Collection<String> ruleIDs = RULE_STORE.retrieveAllIDs();
125         JsonArray jsonARules = new JsonArray();
126         JsonObject jsonObj = new JsonObject();
127         for (String id : ruleIDs) {
128             MCRAccessRule rule = RULE_STORE.getRule(id);
129             JsonObject jsonO = new JsonObject();
130             jsonO.addProperty("ruleID", id);
131             jsonO.addProperty("desc", rule.getDescription());
132             jsonO.addProperty("ruleSt", rule.getRuleString());
133             jsonARules.add(jsonO);
134         }
135         jsonObj.add("rules", jsonARules);
136         JsonArray jsonAAccess = new JsonArray();
137         Collection<String> ids = ACCESS_STORE.getDistinctStringIDs();
138         for (String id : ids) {
139             Collection<String> pools = ACCESS_STORE.getPoolsForObject(id);
140             for (String pool : pools) {
141                 JsonObject jsonO = new JsonObject();
142                 jsonO.addProperty(JSON_ACCESSID, id);
143                 jsonO.addProperty(JSON_ACCESSPOOL, pool);
144                 jsonO.addProperty(JSON_RULE, ACCESS_STORE.getRuleID(id, pool));
145                 jsonAAccess.add(jsonO);
146             }
147         }
148         jsonObj.add("access", jsonAAccess);
149         return jsonObj.toString();
150     }
151 
152     @POST
153     @Consumes(MediaType.APPLICATION_JSON)
154     @MCRRestrictedAccess(MCRAclEditorPermission.class)
155     public Response add(String data) {
156         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
157         String accessID = jsonObject.get(JSON_ACCESSID).getAsString();
158         String accessPool = jsonObject.get(JSON_ACCESSPOOL).getAsString();
159         String rule = jsonObject.get(JSON_RULE).getAsString();
160 
161         if (RULE_STORE.existsRule(rule) && !"".equals(accessID) && !"".equals(accessPool)) {
162             MCRRuleMapping accessRule = createRuleMap(accessID, accessPool, rule);
163 
164             if (!ACCESS_STORE.existsRule(accessID, accessPool)) {
165                 ACCESS_STORE.createAccessDefinition(accessRule);
166                 return Response.ok().build();
167             } else {
168                 return Response.status(Status.CONFLICT).build();
169             }
170         } else {
171             return Response.status(Status.CONFLICT).build();
172         }
173     }
174 
175     @DELETE
176     @Consumes(MediaType.APPLICATION_JSON)
177     @MCRRestrictedAccess(MCRAclEditorPermission.class)
178     public String remove(String data) {
179         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
180         JsonArray jsonArray = jsonObject.getAsJsonArray("access");
181         for (int i = 0; i < jsonArray.size(); i++) {
182             JsonObject accessAsJsonObject = jsonArray.get(i).getAsJsonObject();
183             String accessID = accessAsJsonObject.get(JSON_ACCESSID).getAsString();
184             String accessPool = accessAsJsonObject.get(JSON_ACCESSPOOL).getAsString();
185 
186             if (ACCESS_STORE.existsRule(accessID, accessPool)) {
187                 MCRRuleMapping accessRule = ACCESS_STORE.getAccessDefinition(accessPool, accessID);
188 
189                 if (!"".equals(accessRule.getObjId())) {
190                     ACCESS_STORE.deleteAccessDefinition(accessRule);
191                     accessAsJsonObject.addProperty(JSON_SUCCESS, "1");
192                 } else {
193                     accessAsJsonObject.addProperty(JSON_SUCCESS, "0");
194                 }
195             } else {
196                 accessAsJsonObject.addProperty(JSON_SUCCESS, "0");
197             }
198         }
199         return jsonObject.toString();
200     }
201 
202     @PUT
203     @Consumes(MediaType.APPLICATION_JSON)
204     @MCRRestrictedAccess(MCRAclEditorPermission.class)
205     public Response edit(String data) {
206         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
207         String accessIDOld = jsonObject.get("accessIDOld").getAsString();
208         String accessPoolOld = jsonObject.get("accessPoolOld").getAsString();
209         String mode = jsonObject.get("mode").getAsString();
210         String accessIDNew = jsonObject.get("accessIDNew").getAsString();
211         String accessPoolNew = jsonObject.get("accessPoolNew").getAsString();
212         String accessRuleNew = jsonObject.get("accessRuleNew").getAsString();
213 
214         if (!ACCESS_STORE.existsRule(accessIDNew, accessPoolNew) || JSON_RULE.equals(mode)) {
215             if (ACCESS_STORE.existsRule(accessIDOld, accessPoolOld) && RULE_STORE.existsRule(accessRuleNew)
216                 && !"".equals(accessIDNew) && !"".equals(accessPoolNew)) {
217                 MCRRuleMapping accessRule = createRuleMap(accessIDNew, accessPoolNew, accessRuleNew);
218                 MCRRuleMapping oldAccessRule = ACCESS_STORE.getAccessDefinition(accessPoolOld, accessIDOld);
219 
220                 if (oldAccessRule != null && !oldAccessRule.getObjId().equals("")) {
221                     if (JSON_RULE.equals(mode)) {
222                         ACCESS_STORE.updateAccessDefinition(accessRule);
223                     } else {
224                         ACCESS_STORE.deleteAccessDefinition(oldAccessRule);
225                         ACCESS_STORE.createAccessDefinition(accessRule);
226                     }
227                 } else {
228                     ACCESS_STORE.createAccessDefinition(accessRule);
229                 }
230                 return Response.ok().build();
231             } else {
232                 return Response.status(Status.CONFLICT).build();
233             }
234         } else {
235             return Response.status(Status.CONFLICT).build();
236         }
237     }
238 
239     @POST
240     @Path(JSON_RULE)
241     @MCRRestrictedAccess(MCRAclEditorPermission.class)
242     @Consumes(MediaType.APPLICATION_JSON)
243     public String addRule(String data) {
244         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
245         String ruleDesc = jsonObject.get("ruleDesc").getAsString();
246         String ruleText = jsonObject.get("ruleText").getAsString();
247         MCRAccessRule accessRule;
248 
249         try {
250             accessRule = createAccessRule(ruleDesc, ruleText);
251         } catch (Exception e) {
252             return "";
253         }
254         RULE_STORE.createRule(accessRule);
255         return accessRule.getId();
256     }
257 
258     @DELETE
259     @Path(JSON_RULE)
260     @MCRRestrictedAccess(MCRAclEditorPermission.class)
261     @Consumes(MediaType.APPLICATION_JSON)
262     public Response removeRule(String data) {
263         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
264         String ruleID = jsonObject.get("ruleID").getAsString();
265 
266         if (!ACCESS_STORE.isRuleInUse(ruleID)) {
267             RULE_STORE.deleteRule(ruleID);
268             return Response.ok().build();
269         } else {
270             return Response.status(Status.CONFLICT).build();
271         }
272     }
273 
274     @PUT
275     @Path(JSON_RULE)
276     @MCRRestrictedAccess(MCRAclEditorPermission.class)
277     @Consumes(MediaType.APPLICATION_JSON)
278     public Response editRule(String data) {
279         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
280         String ruleID = jsonObject.get("ruleID").getAsString();
281         String ruleDesc = jsonObject.get("ruleDesc").getAsString();
282         String ruleText = jsonObject.get("ruleText").getAsString();
283         String uid = MCRSessionMgr.getCurrentSession().getUserInformation().getUserID();
284 
285         if (RULE_STORE.existsRule(ruleID)) {
286             try {
287                 MCRAccessRule accessRule = new MCRAccessRule(ruleID, uid, new Date(), ruleText, ruleDesc);
288                 RULE_STORE.updateRule(accessRule);
289                 return Response.ok().build();
290             } catch (Exception e) {
291                 return Response.status(Status.CONFLICT).build();
292             }
293         } else {
294             return Response.status(Status.CONFLICT).build();
295         }
296     }
297 
298     @PUT
299     @Path("multi")
300     @MCRRestrictedAccess(MCRAclEditorPermission.class)
301     @Consumes(MediaType.APPLICATION_JSON)
302     public String editMulti(String data) {
303         JsonObject jsonObject = JsonParser.parseString(data).getAsJsonObject();
304         JsonArray jsonArray = jsonObject.getAsJsonArray("access");
305         for (int i = 0; i < jsonArray.size(); i++) {
306             JsonObject accessAsJsonObject = jsonArray.get(i).getAsJsonObject();
307             String accessID = accessAsJsonObject.get(JSON_ACCESSID).getAsString();
308             String accessPool = accessAsJsonObject.get(JSON_ACCESSPOOL).getAsString();
309             String accessRule = accessAsJsonObject.get("accessRule").getAsString();
310 
311             if (ACCESS_STORE.existsRule(accessID, accessPool) && RULE_STORE.existsRule(accessRule)) {
312                 MCRRuleMapping newAccessRule = createRuleMap(accessID, accessPool, accessRule);
313                 MCRRuleMapping oldAccessRule = ACCESS_STORE.getAccessDefinition(accessPool, accessID);
314 
315                 if (oldAccessRule != null && !oldAccessRule.getObjId().equals("")) {
316                     ACCESS_STORE.updateAccessDefinition(newAccessRule);
317                     accessAsJsonObject.addProperty(JSON_SUCCESS, "1");
318                 } else {
319                     ACCESS_STORE.createAccessDefinition(newAccessRule);
320                     accessAsJsonObject.addProperty(JSON_SUCCESS, "1");
321                 }
322             } else {
323                 accessAsJsonObject.addProperty(JSON_SUCCESS, "0");
324             }
325         }
326         return jsonObject.toString();
327     }
328 
329     private MCRRuleMapping createRuleMap(String accessID, String accessPool, String rule) {
330         String uid = MCRSessionMgr.getCurrentSession().getUserInformation().getUserID();
331         MCRRuleMapping accessRule = new MCRRuleMapping();
332         accessRule.setObjId(accessID);
333         accessRule.setPool(accessPool);
334         accessRule.setRuleId(rule);
335         accessRule.setCreationdate(new Date());
336         accessRule.setCreator(uid);
337         return accessRule;
338     }
339 
340     private MCRAccessRule createAccessRule(String ruleDesc, String ruleText) {
341         int freeRuleID = RULE_STORE.getNextFreeRuleID("SYSTEMRULE");
342         String ruleID = "0000000000" + freeRuleID;
343         ruleID = ruleID.substring(ruleID.length() - "0000000000".length());
344         String newRuleID = "SYSTEMRULE" + ruleID;
345         String uid = MCRSessionMgr.getCurrentSession().getUserInformation().getUserID();
346 
347         return new MCRAccessRule(newRuleID, uid, new Date(), ruleText, ruleDesc);
348     }
349 }