1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package fr.cnes.doi.resource.mds;
20
21 import fr.cnes.doi.application.DoiMdsApplication;
22 import fr.cnes.doi.application.DoiMdsApplication.API_MDS;
23 import fr.cnes.doi.exception.DoiServerException;
24 import fr.cnes.doi.resource.AbstractResource;
25 import static fr.cnes.doi.security.UtilsHeader.SELECTED_ROLE_PARAMETER;
26
27 import fr.cnes.doi.utils.spec.Requirement;
28 import java.util.List;
29
30 import org.apache.logging.log4j.Level;
31 import org.apache.logging.log4j.Logger;
32 import org.restlet.data.MediaType;
33 import org.restlet.ext.wadl.DocumentationInfo;
34 import org.restlet.ext.wadl.MethodInfo;
35 import org.restlet.ext.wadl.RepresentationInfo;
36 import org.restlet.security.Role;
37 import org.restlet.util.Series;
38
39
40
41
42
43
44 public class BaseMdsResource extends AbstractResource {
45
46
47
48
49 public static final String DOI_PARAMETER = "doi";
50
51
52
53
54
55 public static final String URL_PARAMETER = "url";
56
57
58
59 protected volatile Logger LOG;
60
61
62
63
64 private volatile DoiMdsApplication doiApp;
65
66
67
68
69
70
71 @Override
72 protected void doInit() throws DoiServerException {
73 super.doInit();
74 this.doiApp = (DoiMdsApplication) getApplication();
75 LOG = this.doiApp.getLog();
76 LOG.traceEntry();
77 LOG.traceExit();
78 }
79
80
81
82
83
84
85
86 private boolean hasSingleRole(final List<Role> roles) {
87 LOG.traceEntry("Parameter : {}", roles);
88 return LOG.traceExit(roles.size() == 1);
89 }
90
91
92
93
94
95
96
97 private boolean hasNoRole(final List<Role> roles) {
98 LOG.traceEntry("Parameter : {}", roles);
99 return LOG.traceExit(roles.isEmpty());
100 }
101
102
103
104
105
106
107
108 private boolean hasSelectedRole(final String suffusedWithRole) {
109 LOG.traceEntry("Parameter : {}", suffusedWithRole);
110 return LOG.traceExit(!suffusedWithRole.isEmpty());
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 private String getRoleName(final String selectedRole) throws DoiServerException {
129 LOG.traceEntry("Parameter : {}", selectedRole);
130 final String roleName;
131 if (hasSelectedRole(selectedRole)) {
132 roleName = getRoleNameWhenRoleInHeader(selectedRole);
133 } else {
134 roleName = getRoleNameWhenNotProvidedInHeader();
135 }
136 return LOG.traceExit(roleName);
137 }
138
139
140
141
142
143
144 private String getRoleNameWhenNotProvidedInHeader() {
145 LOG.traceEntry();
146
147 final List<Role> roles = getClientInfo().getRoles();
148 if (hasNoRole(roles)) {
149
150 throw LOG.throwing(Level.DEBUG, new DoiServerException(getApplication(),
151 API_MDS.SECURITY_USER_NO_ROLE, "User not contained in any role"));
152 } else if (hasSingleRole(roles)) {
153
154 final Role role = roles.get(0);
155 LOG.debug("User has a single Role {}", role);
156 return LOG.traceExit(role.getName());
157 } else {
158
159 LOG.info("DOIServer : Cannot know which role must be applied");
160 throw LOG.throwing(Level.DEBUG, new DoiServerException(getApplication(),
161 API_MDS.SECURITY_USER_CONFLICT, "Cannot know which role must be applied"));
162 }
163 }
164
165
166
167
168
169
170
171 private String getRoleNameWhenRoleInHeader(final String selectedRole) {
172 LOG.traceEntry("Parameter : {}", selectedRole);
173
174 LOG.debug("Role selected : {}", selectedRole);
175 if (isInRole(selectedRole)) {
176
177 LOG.debug("User is in Role : {}", selectedRole);
178 return LOG.traceExit(selectedRole);
179 } else {
180
181 LOG.debug("User is not in Role : {}", selectedRole);
182 LOG.info("DOIServer : The role {} is not allowed to use this feature", selectedRole);
183 throw LOG.throwing(Level.DEBUG,
184 new DoiServerException(getApplication(),
185 API_MDS.SECURITY_USER_NOT_IN_SELECTED_ROLE,
186 "Fail to make this request with this role (" + selectedRole + ")"));
187 }
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 @Requirement(reqId = Requirement.DOI_AUTO_030, reqName = Requirement.DOI_AUTO_030_NAME)
214 protected void checkPermission(final String doiName, final String selectedRole)
215 throws DoiServerException {
216 LOG.traceEntry("Parameters : {} and {}", doiName, selectedRole);
217 final String prefixCNES = this.getDoiApp().getDataCentrePrefix();
218 final String projectRole = getRoleName(selectedRole);
219 if (!doiName.startsWith(prefixCNES + "/" + projectRole + "/")) {
220 LOG.debug("The DOI {} does not match with {}", doiName,
221 prefixCNES + "/" + projectRole);
222 throw LOG.throwing(Level.DEBUG,
223 new DoiServerException(getApplication(), API_MDS.SECURITY_USER_PERMISSION,
224 "The DOI " + doiName + " does not match with" + prefixCNES + "/"
225 + projectRole));
226 }
227 LOG.traceExit();
228 }
229
230
231
232
233
234
235
236 @Requirement(reqId = Requirement.DOI_AUTO_020, reqName = Requirement.DOI_AUTO_020_NAME)
237 public String extractSelectedRoleFromRequestIfExists() {
238 LOG.traceEntry();
239 final Series headers = (Series) getRequestAttributes().get("org.restlet.http.headers");
240 final String selectedRole = headers.getFirstValue(SELECTED_ROLE_PARAMETER, "");
241 return LOG.traceExit(selectedRole);
242 }
243
244
245
246
247
248
249 protected RepresentationInfo explainRepresentation() {
250 final RepresentationInfo repInfo = new RepresentationInfo();
251 repInfo.setIdentifier("explainRepresentationID");
252 repInfo.setMediaType(MediaType.TEXT_PLAIN);
253 final DocumentationInfo docInfo = new DocumentationInfo();
254 docInfo.setTitle("Body representation");
255 docInfo.setTextContent("short explanation of status code");
256 repInfo.setDocumentation(docInfo);
257 return repInfo;
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272 @Override
273 protected void describeDelete(final MethodInfo info) {
274 addResponseDocToMethod(info, createResponseDoc(API_MDS.SECURITY_USER_NO_ROLE.getStatus(),
275 API_MDS.SECURITY_USER_NO_ROLE.getShortMessage(), "explainRepresentationID"));
276 addResponseDocToMethod(info,
277 createResponseDoc(API_MDS.SECURITY_USER_NOT_IN_SELECTED_ROLE.getStatus(),
278 API_MDS.SECURITY_USER_NOT_IN_SELECTED_ROLE.getShortMessage(),
279 "explainRepresentationID"));
280 addResponseDocToMethod(info, createResponseDoc(API_MDS.SECURITY_USER_PERMISSION.getStatus(),
281 API_MDS.SECURITY_USER_PERMISSION.getShortMessage(), "explainRepresentationID"));
282 addResponseDocToMethod(info, createResponseDoc(API_MDS.SECURITY_USER_CONFLICT.getStatus(),
283 API_MDS.SECURITY_USER_CONFLICT.getShortMessage(), "explainRepresentationID"));
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298 @Override
299 protected void describePost(final MethodInfo info) {
300 addResponseDocToMethod(info, createResponseDoc(API_MDS.SECURITY_USER_NO_ROLE.getStatus(),
301 API_MDS.SECURITY_USER_NO_ROLE.getShortMessage(), explainRepresentation()));
302 addResponseDocToMethod(info,
303 createResponseDoc(API_MDS.SECURITY_USER_NOT_IN_SELECTED_ROLE.getStatus(),
304 API_MDS.SECURITY_USER_NOT_IN_SELECTED_ROLE.getShortMessage(),
305 "explainRepresentationID"));
306 addResponseDocToMethod(info, createResponseDoc(API_MDS.SECURITY_USER_PERMISSION.getStatus(),
307 API_MDS.SECURITY_USER_PERMISSION.getShortMessage(), "explainRepresentationID"));
308 addResponseDocToMethod(info, createResponseDoc(API_MDS.SECURITY_USER_CONFLICT.getStatus(),
309 API_MDS.SECURITY_USER_CONFLICT.getShortMessage(), "explainRepresentationID"));
310 }
311
312
313
314
315
316
317
318 public String getAttributePath(final String basePath) {
319 String resourcePath = getResourcePath();
320 int questionMark = resourcePath.indexOf("?");
321 questionMark = (questionMark == -1) ? resourcePath.length() : questionMark;
322 resourcePath = resourcePath.substring(0, questionMark);
323 return resourcePath.replace(basePath + "/", "");
324 }
325
326
327
328
329
330
331 public DoiMdsApplication getDoiApp() {
332 return doiApp;
333 }
334
335 }