1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.kuali.mobility.push.controllers;
16
17 import java.sql.Timestamp;
18 import java.util.ArrayList;
19 import java.util.Iterator;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Locale;
23 import java.util.Map;
24 import java.util.Properties;
25
26 import javax.annotation.Resource;
27 import javax.servlet.http.HttpServletRequest;
28
29 import net.sf.json.JSONArray;
30 import net.sf.json.JSONException;
31 import net.sf.json.JSONObject;
32 import net.sf.json.JSONSerializer;
33
34 import org.apache.log4j.Logger;
35 import org.kuali.mobility.push.entity.Device;
36 import org.kuali.mobility.push.entity.Push;
37 import org.kuali.mobility.push.entity.PushMessage;
38 import org.kuali.mobility.push.entity.Sender;
39 import org.kuali.mobility.push.service.DeviceService;
40 import org.kuali.mobility.push.service.PushMessageService;
41 import org.kuali.mobility.push.service.PushService;
42 import org.kuali.mobility.push.service.SenderService;
43 import org.kuali.mobility.security.group.api.Group;
44 import org.kuali.mobility.security.user.api.User;
45 import org.kuali.mobility.shared.Constants;
46 import org.kuali.mobility.shared.controllers.AbstractMobilityController;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.beans.factory.annotation.Qualifier;
49 import org.springframework.context.MessageSource;
50 import org.springframework.http.HttpStatus;
51 import org.springframework.http.ResponseEntity;
52 import org.springframework.stereotype.Controller;
53 import org.springframework.ui.Model;
54 import org.springframework.validation.BindingResult;
55 import org.springframework.validation.Errors;
56 import org.springframework.web.bind.annotation.ModelAttribute;
57 import org.springframework.web.bind.annotation.PathVariable;
58 import org.springframework.web.bind.annotation.RequestBody;
59 import org.springframework.web.bind.annotation.RequestMapping;
60 import org.springframework.web.bind.annotation.RequestMethod;
61 import org.springframework.web.bind.annotation.RequestParam;
62 import org.springframework.web.bind.annotation.ResponseBody;
63 import org.springframework.web.servlet.LocaleResolver;
64 import org.springframework.web.servlet.support.RequestContextUtils;
65
66
67
68
69
70
71
72 @Controller
73 @RequestMapping("/push")
74 public class PushController extends AbstractMobilityController {
75
76
77
78
79 private static final Logger LOG = Logger.getLogger(PushController.class);
80
81 private static final String RECIPIENTS = "recipients";
82
83 @Resource(name = "messageSource")
84 private MessageSource messageSource;
85
86 @Autowired
87 @Qualifier("kmeProperties")
88 private Properties kmeProperties;
89
90 @Autowired
91 @Qualifier("senderKeysProperties")
92 private Properties senderKeysProperties;
93
94
95
96
97
98 private String keyListFile;
99
100 private Map<String, String> stockPushMessages;
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 private static final Map<String, String> RECIPIENTS_MAP;
137
138 static {
139 RECIPIENTS_MAP = new LinkedHashMap<String, String>();
140
141 RECIPIENTS_MAP.put("All", "all");
142 RECIPIENTS_MAP.put("All without Network ID", "usernameless");
143 }
144
145
146
147
148 @Autowired
149 private PushService pushService;
150
151
152
153
154 @Autowired
155 private DeviceService deviceService;
156
157
158
159
160 @Autowired
161 private SenderService senderService;
162
163 @Autowired
164 private PushMessageService pushMessageService;
165
166
167
168
169
170
171
172
173
174
175 @SuppressWarnings("unchecked")
176 @RequestMapping(value = "/detail/{pushHash}", method = RequestMethod.GET)
177 public String getPushDetails(Model uiModel, HttpServletRequest request,
178 @PathVariable("pushHash") Long pushHash) {
179
180 String isAdmin = "no";
181 if (isAllowedAccess("KME-ADMINISTRATOR", request)) {
182 isAdmin = "yes";
183 }
184 User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
185 List<Group> groups = user.getGroups();
186 Iterator<Group> it = groups.iterator();
187 while(it.hasNext()){
188 Group group = it.next();
189 if("KME-ADMINISTRATOR".equals(group.getName())){
190 isAdmin = "yes";
191 }
192 }
193 uiModel.addAttribute("isAdminMember", isAdmin);
194
195 if (pushHash != null) {
196 LOG.info("PushID is :" + pushHash);
197 } else {
198 return "push";
199 }
200 Push push = pushService.findPushById(pushHash);
201 uiModel.addAttribute("thispush", push);
202
203 List<Device> devices = pushService.findDevicesForPush(push);
204 LOG.info("Found Devices for Push " + devices.size());
205 uiModel.addAttribute("thesedevices", devices);
206 return "push/pushdetail";
207 }
208
209
210
211
212
213
214
215
216
217
218 @Deprecated
219 @RequestMapping(value = "/send", method = RequestMethod.GET)
220 public String sendToChosenDevice(Model uiModel, HttpServletRequest request,
221 @RequestParam(value = "id", required = false) long deviceID) {
222 String viewName = "push/index";
223 if (!isAllowedAccess("KME-ADMINISTRATOR", request)) {
224 viewName = "redirect:/errors/401";
225 } else {
226 stockPushMessages = getPushMessages();
227 uiModel.addAttribute(RECIPIENTS, RECIPIENTS_MAP);
228 uiModel.addAttribute("stockPushMessages", stockPushMessages);
229 Push push = new Push();
230 Device device = deviceService.findDeviceById(deviceID);
231 uiModel.addAttribute("push", push);
232 uiModel.addAttribute("device", device);
233 }
234
235 if( "3".equalsIgnoreCase( getKmeProperties().getProperty("kme.uiVersion","classic") ) ) {
236 viewName = "ui3/push/index";
237 }else{
238 viewName = "push/index";
239 }
240 return viewName;
241 }
242
243
244
245
246
247
248
249
250 @RequestMapping(value = "test", method = RequestMethod.GET)
251 @ResponseBody
252 public String test(Model uiModel, HttpServletRequest request) {
253 return "WTF!";
254 }
255
256 @RequestMapping(value = "error", method = RequestMethod.GET)
257 public String error(Model uiModel, HttpServletRequest request) {
258 return "redirect:/errors/401";
259 }
260
261
262
263
264
265
266
267
268
269 @RequestMapping(value = "", method = RequestMethod.GET)
270 public String index(Model uiModel, HttpServletRequest request) {
271 LOG.info("index() in Push Tool was called." );
272
273 String viewName;
274 if (!isAllowedAccess("KME-ADMINISTRATOR", request)) {
275 viewName = "redirect:/errors/401.jsp";
276 LOG.info("Redirecting to: " + viewName );
277 } else {
278
279 String source = getKmeProperties().getProperty("push.stock.messages.source");
280 if ("database".equalsIgnoreCase(source)) {
281 LOG.info("GET Stock Messages from DB.");
282 LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
283 Locale locale = localeResolver.resolveLocale(request);
284 this.setStockPushMessages(this.getPushMessages(locale));
285 } else if ("properties".equalsIgnoreCase(source)) {
286 LOG.info("GET Stock Messages from Properties.");
287 this.setStockPushMessages(this.getPushMessages());
288 }
289
290 uiModel.addAttribute(RECIPIENTS, RECIPIENTS_MAP);
291 uiModel.addAttribute("stockPushMessages", stockPushMessages);
292 Push push = new Push();
293
294 LOG.info("keyListFile: " + keyListFile);
295
296 uiModel.addAttribute("push", push);
297
298 if( "3".equalsIgnoreCase( getKmeProperties().getProperty("kme.uiVersion","classic") ) ) {
299 viewName = "ui3/push/index";
300 }else{
301 viewName = "push/index";
302 }
303 }
304 return viewName;
305 }
306
307 @RequestMapping(value = "/js/history.js")
308 public String getHistoryJavaScript(Model uiModel, HttpServletRequest request) {
309 return "ui3/push/js/history";
310 }
311
312 @RequestMapping(value = "/js/push.js")
313 public String getJavaScript(Model uiModel, HttpServletRequest request) {
314 String source = getKmeProperties().getProperty("push.stock.messages.source");
315 if ("database".equalsIgnoreCase(source)) {
316 LOG.info("GET Stock Messages from DB.");
317 LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
318 Locale locale = localeResolver.resolveLocale(request);
319 this.setStockPushMessages(this.getPushMessages(locale));
320 } else if ("properties".equalsIgnoreCase(source)) {
321 LOG.info("GET Stock Messages from Properties.");
322 this.setStockPushMessages(this.getPushMessages());
323 }
324
325 Sender defaultSender = senderService.findSenderByShortName("KME_PUSH");
326 uiModel.addAttribute("senderKey", defaultSender.getSenderKey());
327
328 uiModel.addAttribute(RECIPIENTS, RECIPIENTS_MAP);
329 uiModel.addAttribute("stockPushMessages", stockPushMessages);
330
331 return "ui3/push/js/push";
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345 @Deprecated
346 @RequestMapping(value = "/get/{pushId}", method = RequestMethod.GET)
347 @ResponseBody
348 public String getUserDetails(Model uiModel, HttpServletRequest request,
349 @PathVariable("pushId") Long pushId) {
350 Push push = new Push();
351 push = pushService.findPushById(pushId);
352
353
354
355 String value = "pushJSON('" + JSONSerializer.toJSON(push).toString() + "');";
356
357
358 return value;
359 }
360
361
362
363
364
365
366
367
368
369 @RequestMapping(value = "/history", method = RequestMethod.GET)
370 public String history(HttpServletRequest request, Model uiModel,
371 @RequestParam(value = "key", required = false) String key) {
372 if( "3".equalsIgnoreCase( getKmeProperties().getProperty("kme.uiVersion","classic") ) ) {
373 return "ui3/push/pushhistory";
374 }
375
376 int pushCount = pushService.countPushes();
377 uiModel.addAttribute("pushCount", pushCount);
378
379 List<Push> pastPushes = pushService.findAllPush();
380 uiModel.addAttribute("pastPushes", pastPushes);
381
382 return "push/history";
383 }
384
385
386
387
388
389
390
391
392
393
394 @RequestMapping(value = "/remove/{pushHash}", method = RequestMethod.GET)
395 public String remove(HttpServletRequest request,
396 Model uiModel,
397 @RequestParam(value = "key", required = false) String key,
398 @PathVariable("pushHash") Long pushHash) {
399 String viewName;
400 if (!isAllowedAccess("KME-ADMINISTRATOR", request)) {
401 viewName = "redirect:/errors/401";
402 } else {
403 Push push = null;
404 if (pushHash != null) {
405 push = pushService.findPushById(pushHash.longValue());
406 }
407 if (push != null) {
408 if (pushService.removePush(push)) {
409 LOG.info("Removed a Push from History");
410 } else {
411 LOG.info("Failed to removed a Push from History");
412 }
413 } else {
414 LOG.info("No Push found to be removed.");
415 }
416
417 int pushCount = pushService.countPushes();
418 uiModel.addAttribute("pushCount", pushCount);
419
420 List<Push> pastPushes = pushService.findAllPush();
421 uiModel.addAttribute("pastPushes", pastPushes);
422 viewName = "push/history";
423 }
424 return viewName;
425 }
426
427
428
429
430
431
432
433
434
435
436
437
438
439 @RequestMapping(method = RequestMethod.POST)
440 public String submitPush(
441 HttpServletRequest request,
442 Model uiModel,
443 @ModelAttribute("Push") Push push,
444 BindingResult result,
445 @RequestParam(value = "id", required = false) Long id,
446 @RequestParam(value = "sender", required = false) String sender,
447 @RequestParam(value = "recipientSelect", required = false) String recipient) {
448 String viewName;
449 if (!isAllowedAccess("KME-ADMINISTRATOR", request)) {
450 viewName = "redirect:/errors/401";
451 } else {
452 push.setPostedTimestamp(new Timestamp(System.currentTimeMillis()));
453 Sender defaultSender = senderService.findSenderByShortName("KME_PUSH");
454 LOG.info(defaultSender);
455
456 if (defaultSender != null) {
457 push.setSender(defaultSender.getShortName());
458 } else {
459 push.setSender("KME_PUSH");
460 }
461
462
463 LOG.info("---- Recipient Select: " + recipient);
464
465 List<Device> devices = new ArrayList<Device>();
466
467 if (id != null) {
468 LOG.info("---- Selected ID");
469 devices.add(deviceService.findDeviceById((long) id));
470 }
471
472 if (recipient != null) {
473 if (recipient.equals("all")) {
474 devices = deviceService.findAllDevices();
475 } else if (recipient.equals("usernameless")) {
476 devices = deviceService.findDevicesWithoutUsername();
477 }
478 }
479
480 LOG.info(devices.size() + " devices in list");
481
482 if (isValidPush(push, result)) {
483
484 pushService.savePush(push, devices);
485
486
487
488 int pushed = pushService.sendPush(push, devices);
489 LOG.info("Pushed Count: " + pushed);
490 push.setRecipients(pushed);
491 pushService.savePush(push);
492 LOG.info("Post Push:" + push.toString());
493
494 int pushCount = pushService.countPushes();
495 uiModel.addAttribute("pushCount", pushCount);
496
497 List<Push> pastPushes = pushService.findAllPush();
498 uiModel.addAttribute("pastPushes", pastPushes);
499 viewName = "push/history";
500 } else {
501 viewName = "push/index";
502 }
503 }
504 return viewName;
505 }
506
507
508
509
510
511
512
513
514 private boolean isValidPush(Push p, BindingResult result) {
515 Errors errors = ((Errors) result);
516 boolean isValid = true;
517 if (p.getMessage() == null || "".equals(p.getMessage().trim())) {
518 errors.rejectValue("message",
519 "Please type a Message for the Push notification.");
520 isValid = false;
521 }
522 if (p.getTitle() == null || "".equals(p.getTitle().trim())) {
523 errors.rejectValue("title",
524 "Please type a Title for the Push notification.");
525 isValid = false;
526 }
527
528 return isValid;
529 }
530
531
532
533
534
535
536
537 @RequestMapping(value = "/service", method = RequestMethod.POST)
538 public ResponseEntity<String> service(
539 HttpServletRequest request,
540 @RequestParam(value = "data", required = true) String data) {
541 if (!isAllowedAccess("KME-ADMINISTRATOR", request)) {
542 return new ResponseEntity<String>(HttpStatus.FORBIDDEN);
543 } else {
544 LOG.info("Service JSON: " + data);
545 JSONObject queryParams;
546 List<Device> devices = new ArrayList<Device>();
547 String title;
548 String message;
549 String url;
550 String recipient;
551 String sender = "KME_PUSH";
552 String senderKey;
553 JSONArray recipients;
554 try {
555
556
557 queryParams = (JSONObject) JSONSerializer.toJSON(data);
558 title = queryParams.getString("title");
559 message = queryParams.getString("message");
560 url = queryParams.getString("url");
561 senderKey = queryParams.getString("senderKey");
562
563 String source = getKmeProperties().getProperty("push.sender.key.source", "database");
564 if("database".equalsIgnoreCase(source)){
565 LOG.info("Getting SenderKeys from database.");
566 Sender senderObj = senderService.findSenderBySenderKey(senderKey);
567 if (senderObj == null) {
568 LOG.info("---- " + senderKey + " is Not in LHM. May not Send Push Notifications");
569 return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
570 } else {
571 sender = senderObj.getShortName();
572 }
573 }else if("properties".equalsIgnoreCase(source)){
574 LOG.info("Getting SenderKeys from properties file.");
575 String shortName = getSenderKeysProperties().getProperty(senderKey);
576 if(shortName == null){
577 LOG.info("---- " + senderKey + " is Not in LHM. May not Send Push Notifications");
578 return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
579 }else{
580 sender = shortName;
581 }
582 }
583
584
585 if (queryParams.has(RECIPIENTS)) {
586 if ("net.sf.json.JSONArray".equals(queryParams.get(RECIPIENTS).getClass().getName())) {
587
588 recipients = queryParams.getJSONArray(RECIPIENTS);
589 LOG.info("recipients: " + recipients.toString());
590 Iterator i = recipients.iterator();
591 while (i.hasNext()) {
592 String username = i.next().toString();
593 LOG.info("username: " + username);
594 devices.addAll(deviceService
595 .findDevicesByUsername(username));
596 }
597 } else {
598 recipient = queryParams.getString("recipients");
599 LOG.info(recipient);
600 }
601 }
602 if (queryParams.has("devices") && "net.sf.json.JSONArray".equals(queryParams.get("devices").getClass().getName()) ) {
603 JSONArray jDevices = queryParams.getJSONArray("devices");
604 LOG.info("devices: " + jDevices.toString());
605 Iterator i = jDevices.iterator();
606 while (i.hasNext()) {
607 String sDevice = i.next().toString();
608 LOG.info("device: " + sDevice);
609 devices.add(deviceService.findDeviceByDeviceId(sDevice));
610 }
611 }
612
613 } catch (JSONException je) {
614 LOG.error("JSONException in :" + data + " : " + je.getMessage());
615 return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
616 } catch (ClassCastException cce) {
617 LOG.error(cce.getLocalizedMessage(), cce);
618 return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
619 }
620
621 Push push = new Push();
622 push.setEmergency(false);
623 push.setMessage(message);
624 push.setTitle(title);
625 push.setUrl(url);
626 push.setSender(sender);
627 push.setPostedTimestamp(new Timestamp(System.currentTimeMillis()));
628 pushService.savePush(push);
629 int pushed = pushService.sendPush(push, devices);
630 push.setRecipients(pushed);
631 pushService.savePush(push);
632 LOG.info(push.toString());
633
634 return new ResponseEntity<String>(HttpStatus.OK);
635 }
636 }
637
638
639
640
641
642
643
644
645
646
647
648 @Deprecated
649 @RequestMapping(value = "/received", method = RequestMethod.GET)
650 public ResponseEntity<String> receivedNotification(@RequestBody String data) {
651 try {
652 JSONObject inform = (JSONObject) JSONSerializer.toJSON(data);
653 String deviceId = inform.getString("deviceId");
654 List<Device> d = deviceService.findDevicesByDeviceId(deviceId);
655 if (d == null || d.size() == 0) {
656 return new ResponseEntity<String>(HttpStatus.OK);
657 }
658
659
660
661
662
663
664 } catch (JSONException je) {
665 LOG.error("JSONException in :" + data + " : " + je.getMessage());
666 return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
667 } catch (ClassCastException cce) {
668 LOG.error(cce.getLocalizedMessage(), cce);
669 return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
670 }
671 return new ResponseEntity<String>(HttpStatus.OK);
672 }
673
674
675
676
677
678
679
680 public Map<String, String> getPushMessages() {
681 Map<String, String> pushMessages = new LinkedHashMap<String, String>();
682 String stockPushMessage1 = messageSource.getMessage(
683 "push.test.message.stg", null, null);
684 String stockPushMessage2 = messageSource.getMessage(
685 "push.new.feature.kme", null, null);
686 String stockPushMessage3 = messageSource.getMessage(
687 "push.log.protected.tool", null, null);
688 String stockPushMessage4 = messageSource.getMessage(
689 "push.tornado.warning", null, null);
690 String stockPushMessage5 = messageSource.getMessage(
691 "push.crime.local.car.thieves", null, null);
692 pushMessages.put("Test Message STG", stockPushMessage1);
693 pushMessages.put("New Feature in KME", stockPushMessage2);
694 pushMessages.put("Log into a protected tool", stockPushMessage3);
695 pushMessages.put("Tornado Warning", stockPushMessage4);
696 pushMessages.put("Crime: Local Car Thieves", stockPushMessage5);
697 return pushMessages;
698 }
699
700
701
702
703
704
705
706
707 public Map<String, String> getPushMessages(Locale locale) {
708 List<PushMessage> pms = pushMessageService.findAllPushMessagesByLanguage(locale.getLanguage());
709 Map<String, String> pushMessages = new LinkedHashMap<String, String>();
710 Iterator<PushMessage> it = pms.iterator();
711 while (it.hasNext()) {
712 PushMessage pm = it.next();
713 pushMessages.put(pm.getTitle(), pm.getMessage());
714 }
715 return pushMessages;
716 }
717
718
719
720
721
722
723
724 public void setKeyListFile(String keyListFile) {
725 this.keyListFile = keyListFile;
726 }
727
728
729
730
731
732
733 public String getKeyListFile() {
734 return this.keyListFile;
735 }
736
737
738
739
740
741
742 public void setPushService(PushService pushService) {
743 this.pushService = pushService;
744 }
745
746
747
748
749
750
751 public void setDeviceService(DeviceService deviceService) {
752 this.deviceService = deviceService;
753 }
754
755
756
757
758
759
760 public void setSenderService(SenderService senderService) {
761 this.senderService = senderService;
762 }
763
764 public SenderService getSenderService() {
765 return senderService;
766 }
767
768
769
770
771 public MessageSource getMessageSource() {
772 return messageSource;
773 }
774
775
776
777
778 public void setMessageSource(MessageSource messageSource) {
779 this.messageSource = messageSource;
780 }
781
782
783
784
785
786 public void setPushMessageService(PushMessageService pmService) {
787 this.pushMessageService = pmService;
788 }
789
790
791
792
793
794 public Map<String, String> getStockPushMessages() {
795 return stockPushMessages;
796 }
797
798
799
800
801 public void setStockPushMessages(Map<String, String> stockPushMessages) {
802 this.stockPushMessages = stockPushMessages;
803 }
804
805
806
807
808 public Properties getKmeProperties() {
809 return kmeProperties;
810 }
811
812
813
814
815 public void setKmeProperties(Properties kmeProperties) {
816 this.kmeProperties = kmeProperties;
817 }
818
819
820
821
822 public Properties getSenderKeysProperties() {
823 return senderKeysProperties;
824 }
825
826
827
828
829
830 public void setSenderKeysProperties(Properties senderKeysProperties) {
831 this.senderKeysProperties = senderKeysProperties;
832 }
833 }