1 package net.avcompris.examples.users3.web;
2
3 import static com.google.common.base.Preconditions.checkNotNull;
4 import static net.avcompris.commons3.databeans.DataBeans.instantiate;
5 import static net.avcompris.examples.users3.web.Application.API;
6 import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
7 import static org.springframework.web.bind.annotation.RequestMethod.GET;
8 import static org.springframework.web.bind.annotation.RequestMethod.POST;
9 import static org.springframework.web.bind.annotation.RequestMethod.PUT;
10
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13
14 import org.apache.commons.logging.Log;
15 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.http.HttpStatus;
17 import org.springframework.http.ResponseEntity;
18 import org.springframework.web.bind.annotation.PathVariable;
19 import org.springframework.web.bind.annotation.RequestBody;
20 import org.springframework.web.bind.annotation.RequestMapping;
21 import org.springframework.web.bind.annotation.RequestParam;
22 import org.springframework.web.bind.annotation.RestController;
23
24 import net.avcompris.commons3.api.EntitiesQueryRaw;
25 import net.avcompris.commons3.api.exception.ServiceException;
26 import net.avcompris.commons3.client.SessionPropagator;
27 import net.avcompris.commons3.core.AuthService;
28 import net.avcompris.commons3.core.CorrelationService;
29 import net.avcompris.commons3.utils.Clock;
30 import net.avcompris.commons3.utils.LogFactory;
31 import net.avcompris.examples.users3.api.PreferredLang;
32 import net.avcompris.examples.users3.api.PreferredTimeZone;
33 import net.avcompris.examples.users3.api.UserCreate;
34 import net.avcompris.examples.users3.api.UserInfo;
35 import net.avcompris.examples.users3.api.UserUpdate;
36 import net.avcompris.examples.users3.api.UsersInfo;
37 import net.avcompris.examples.users3.api.UsersQuery;
38 import net.avcompris.examples.users3.core.api.UsersService;
39 import net.avcompris.examples.users3.query.UserFiltering;
40
41 @RestController
42 public final class UsersController extends MyAbstractController {
43
44 private static final Log logger = LogFactory.getLog(UsersController.class);
45
46 private final AuthService authService;
47 private final UsersService usersService;
48
49 @Autowired
50 public UsersController(final CorrelationService correlationService, final AuthService authService,
51 final UsersService usersService,
52 final SessionPropagator sessionPropagator,
53 final Clock clock) {
54
55 super(correlationService, sessionPropagator, clock);
56
57 this.authService = checkNotNull(authService, "authService");
58 this.usersService = checkNotNull(usersService, "usersService");
59 }
60
61 @RequestMapping(value = API + "/users", method = GET)
62 public ResponseEntity<UsersInfo> getUsers(final HttpServletRequest request,
63 final HttpServletResponse response,
64 @RequestParam(name = "q", required = false) final String q,
65 @RequestParam(name = "sort", required = false) final String sort,
66 @RequestParam(name = "start", required = false) final Integer start,
67 @RequestParam(name = "limit", required = false) final Integer limit,
68 @RequestParam(name = "expand", required = false) final String expand
69 ) throws ServiceException {
70
71 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
72
73 final UsersQuery query = usersService.validateUsersQuery(correlationId, user, q, sort, start, limit,
74 expand);
75
76 final UsersInfo users = usersService.getUsers(correlationId, user, query);
77
78 return ResponseEntity.status(HttpStatus.OK)
79 .body(users);
80 });
81 }
82
83 @RequestMapping(value = API + "/users", method = POST)
84 public ResponseEntity<UsersInfo> getUsers(final HttpServletRequest request,
85 final HttpServletResponse response,
86 @RequestBody(required = true) final EntitiesQueryRaw<UserFiltering, UserFiltering.Field> raw
87 ) throws ServiceException {
88
89 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
90
91 final UsersQuery query = usersService.validateUsersQuery(correlationId, user, raw.getQ(), raw.getSort(),
92 raw.getStart(), raw.getLimit(), raw.getExpand());
93
94 final UsersInfo users = usersService.getUsers(correlationId, user, query);
95
96 return ResponseEntity.status(HttpStatus.OK)
97 .body(users);
98 });
99 }
100
101 @RequestMapping(value = API + "/users/{username}", method = POST)
102 public ResponseEntity<UserInfo> createUser(final HttpServletRequest request,
103 final HttpServletResponse response,
104 @PathVariable(name = "username", required = true) final String username,
105 @RequestBody(required = true) final UserCreate create
106 ) throws ServiceException {
107
108 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
109
110 final UserInfo userInfo = usersService.createUser(correlationId, user, username, create);
111
112 return ResponseEntity.status(HttpStatus.CREATED)
113 .body(userInfo);
114 });
115 }
116
117 @RequestMapping(value = API + "/users/me", method = GET)
118 public ResponseEntity<UserInfo> getUserMe(final HttpServletRequest request,
119 final HttpServletResponse response
120 ) throws ServiceException {
121
122 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
123
124 final UserInfo userInfo = usersService.getUserMe(correlationId, user);
125
126 return ResponseEntity.status(HttpStatus.OK)
127 .body(userInfo);
128 });
129 }
130
131 @RequestMapping(value = API + "/users/{username}", method = GET)
132 public ResponseEntity<UserInfo> getUser(final HttpServletRequest request,
133 final HttpServletResponse response,
134 @PathVariable(name = "username", required = true) final String username
135 ) throws ServiceException {
136
137 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
138
139 final UserInfo userInfo;
140
141 if (username.contentEquals(user.getUsername())) {
142
143 userInfo = usersService.getUserMe(correlationId, user);
144
145 } else {
146
147 userInfo = usersService.getUser(correlationId, user, username);
148 }
149
150 return ResponseEntity.status(HttpStatus.OK)
151 .body(userInfo);
152 });
153 }
154
155 @RequestMapping(value = API + "/users/me/preferredLang", method = GET)
156 public ResponseEntity<String> getUserMePreferredLang(final HttpServletRequest request,
157 final HttpServletResponse response
158 ) throws ServiceException {
159
160 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
161
162 final UserInfo userInfo = usersService.getUserMe(correlationId, user);
163
164 final String lang = userInfo.getPreferredLang();
165
166 return ResponseEntity.status(lang != null
167 ? HttpStatus.OK
168 : HttpStatus.NO_CONTENT)
169 .body(lang);
170 });
171 }
172
173 @RequestMapping(value = API + "/users/me/preferredLang", method = { PUT, POST })
174 public ResponseEntity<String> setUserMePreferredLang(final HttpServletRequest request,
175 final HttpServletResponse response,
176 @RequestBody(required = false) final PreferredLang preferredLang,
177 @RequestParam(name = "preferredLang", required = false) final String preferredLangParam
178 ) throws ServiceException {
179
180 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
181
182 if (logger.isDebugEnabled()) {
183 logger.debug("setUserMePreferredLang(), user: " + user.getUsername() + ", preferredLang: " + preferredLang
184 + ", preferredLangParam: " + preferredLangParam);
185 }
186
187 final String lang;
188
189 if (preferredLangParam != null) {
190
191 lang = preferredLangParam;
192
193 } else if (preferredLang == null) {
194
195 throw new IllegalArgumentException("lang should be set");
196
197 } else {
198
199 lang = preferredLang.getLang();
200 }
201
202 final int fromRevision = usersService.getUserMe(correlationId, user).getRevision();
203
204 usersService.updateUserMe(correlationId, user, instantiate(UserUpdate.class)
205 .setPreferredLang(lang)
206 .setFromRevision(fromRevision));
207
208 final UserInfo userInfo = usersService.getUserMe(correlationId, user);
209
210 return ResponseEntity.status(HttpStatus.OK)
211 .body(userInfo.getPreferredLang());
212 });
213 }
214
215 @RequestMapping(value = API + "/users/{username}/preferredLang", method = GET)
216 public ResponseEntity<String> getUserPreferredLang(final HttpServletRequest request,
217 final HttpServletResponse response,
218 @PathVariable(name = "username", required = true) final String username
219 ) throws ServiceException {
220
221 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
222
223 final UserInfo userInfo;
224
225 if (username.contentEquals(user.getUsername())) {
226
227 userInfo = usersService.getUserMe(correlationId, user);
228
229 } else {
230
231 userInfo = usersService.getUser(correlationId, user, username);
232 }
233
234 final String lang = userInfo.getPreferredLang();
235
236 return ResponseEntity.status(lang != null
237 ? HttpStatus.OK
238 : HttpStatus.NO_CONTENT)
239 .body(lang);
240 });
241 }
242
243 @RequestMapping(value = API + "/users/{username}/preferredLang", method = { POST, PUT })
244 public ResponseEntity<String> setUserPreferredLang(final HttpServletRequest request,
245 final HttpServletResponse response,
246 @PathVariable(name = "username", required = true) final String username,
247 @RequestBody(required = false) final PreferredLang preferredLang,
248 @RequestParam(name = "preferredLang", required = false) final String preferredLangParam
249 ) throws ServiceException {
250
251 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
252
253 final String lang;
254
255 if (preferredLangParam != null) {
256
257 lang = preferredLangParam;
258
259 } else if (preferredLang == null) {
260
261 throw new IllegalArgumentException("lang should be set");
262
263 } else {
264
265 lang = preferredLang.getLang();
266 }
267
268 final UserInfo userInfo;
269
270 if (username.contentEquals(user.getUsername())) {
271
272 final int fromRevision = usersService.getUserMe(correlationId, user).getRevision();
273
274 usersService.updateUserMe(correlationId, user, instantiate(UserUpdate.class)
275 .setPreferredLang(lang)
276 .setFromRevision(fromRevision));
277
278 userInfo = usersService.getUserMe(correlationId, user);
279
280 } else {
281
282 final int fromRevision = usersService.getUser(correlationId, user, username).getRevision();
283
284 usersService.updateUser(correlationId, user, username, instantiate(UserUpdate.class)
285 .setPreferredLang(lang)
286 .setFromRevision(fromRevision));
287
288 userInfo = usersService.getUser(correlationId, user, username);
289 }
290
291 return ResponseEntity.status(HttpStatus.OK)
292 .body(userInfo.getPreferredLang());
293 });
294 }
295
296 @RequestMapping(value = API + "/users/me/preferredTimeZone", method = GET)
297 public ResponseEntity<String> getUserMePreferredTimeZone(final HttpServletRequest request,
298 final HttpServletResponse response
299 ) throws ServiceException {
300
301 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
302
303 final UserInfo userInfo = usersService.getUserMe(correlationId, user);
304
305 final String timeZone = userInfo.getPreferredTimeZone();
306
307 return ResponseEntity.status(timeZone != null
308 ? HttpStatus.OK
309 : HttpStatus.NO_CONTENT)
310 .body(timeZone);
311 });
312 }
313
314 @RequestMapping(value = API + "/users/me/preferredTimeZone", method = { PUT, POST })
315 public ResponseEntity<String> setUserMePreferredTimeZone(final HttpServletRequest request,
316 final HttpServletResponse response,
317 @RequestBody(required = false) final PreferredTimeZone preferredTimeZone,
318 @RequestParam(required = false) final String timeZoneParam
319 ) throws ServiceException {
320
321 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
322
323 final String timeZone;
324
325 if (timeZoneParam != null) {
326
327 timeZone = timeZoneParam;
328
329 } else if (preferredTimeZone == null) {
330
331 throw new IllegalArgumentException("timeZone should be set");
332
333 } else {
334
335 timeZone = preferredTimeZone.getTimeZone();
336 }
337
338 final int fromRevision = usersService.getUserMe(correlationId, user).getRevision();
339
340 usersService.updateUserMe(correlationId, user, instantiate(UserUpdate.class)
341 .setPreferredTimeZone(timeZone)
342 .setFromRevision(fromRevision));
343
344 final UserInfo userInfo = usersService.getUserMe(correlationId, user);
345
346 return ResponseEntity.status(HttpStatus.OK)
347 .body(userInfo.getPreferredTimeZone());
348 });
349 }
350
351 @RequestMapping(value = API + "/users/{username}", method = PUT)
352 public ResponseEntity<UserInfo> updateUser(final HttpServletRequest request,
353 final HttpServletResponse response,
354 @PathVariable(name = "username", required = true) final String username,
355 @RequestBody(required = true) final UserUpdate update
356 ) throws ServiceException {
357
358 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
359
360 final UserInfo userInfo = usersService.updateUser(correlationId, user, username, update);
361
362 return ResponseEntity.status(HttpStatus.OK)
363 .body(userInfo);
364 });
365 }
366
367 @RequestMapping(value = API + "/users/{username}", method = DELETE)
368 public ResponseEntity<String> deleteUser(final HttpServletRequest request,
369 final HttpServletResponse response,
370 @PathVariable(name = "username", required = true) final String username
371 ) throws ServiceException {
372
373 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
374
375 usersService.deleteUser(correlationId, user, username);
376
377 return ResponseEntity.status(HttpStatus.NO_CONTENT)
378 .body(null);
379 });
380 }
381
382 @RequestMapping(value = API + "/users/{username}/preferredTimeZone", method = GET)
383 public ResponseEntity<String> getUserPreferredTimeZone(final HttpServletRequest request,
384 final HttpServletResponse response,
385 @PathVariable(name = "username", required = true) final String username
386 ) throws ServiceException {
387
388 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
389
390 final UserInfo userInfo;
391
392 if (username.contentEquals(user.getUsername())) {
393
394 userInfo = usersService.getUserMe(correlationId, user);
395
396 } else {
397
398 userInfo = usersService.getUser(correlationId, user, username);
399 }
400
401 final String timeZone = userInfo.getPreferredTimeZone();
402
403 return ResponseEntity.status(timeZone != null
404 ? HttpStatus.OK
405 : HttpStatus.NO_CONTENT)
406 .body(timeZone);
407 });
408 }
409
410 @RequestMapping(value = API + "/users/{username}/preferredTimeZone", method = { POST, PUT })
411 public ResponseEntity<String> setUserPreferredTimeZone(final HttpServletRequest request,
412 final HttpServletResponse response,
413 @PathVariable(name = "username", required = true) final String username,
414 @RequestBody(required = false) final PreferredTimeZone preferredTimeZone,
415 @RequestParam(name = "preferredTimeZone", required = false) final String preferredTimeZoneParam
416 ) throws ServiceException {
417
418 return wrapAuthenticated(request, response, authService, (correlationId, user) -> {
419
420 final String timeZone;
421
422 if (preferredTimeZoneParam != null) {
423
424 timeZone = preferredTimeZoneParam;
425
426 } else if (preferredTimeZone == null) {
427
428 throw new IllegalArgumentException("timeZone should be set");
429
430 } else {
431
432 timeZone = preferredTimeZone.getTimeZone();
433 }
434
435 final UserInfo userInfo;
436
437 if (username.contentEquals(user.getUsername())) {
438
439 final int fromRevision = usersService.getUserMe(correlationId, user).getRevision();
440
441 usersService.updateUserMe(correlationId, user, instantiate(UserUpdate.class)
442 .setPreferredTimeZone(timeZone)
443 .setFromRevision(fromRevision));
444
445 userInfo = usersService.getUserMe(correlationId, user);
446
447 } else {
448
449 final int fromRevision = usersService.getUser(correlationId, user, username).getRevision();
450
451 usersService.updateUser(correlationId, user, username, instantiate(UserUpdate.class)
452 .setPreferredTimeZone(timeZone)
453 .setFromRevision(fromRevision));
454
455 userInfo = usersService.getUser(correlationId, user, username);
456 }
457
458 return ResponseEntity.status(HttpStatus.OK)
459 .body(userInfo.getPreferredTimeZone());
460 });
461 }
462 }