|
2 | 2 |
|
3 | 3 | import com.conveyal.datatools.common.utils.SparkUtils;
|
4 | 4 | import com.conveyal.datatools.manager.auth.Auth0UserProfile;
|
5 |
| -import com.conveyal.datatools.manager.models.FeedSource; |
6 |
| -import com.conveyal.datatools.manager.models.JsonViews; |
7 |
| -import com.conveyal.datatools.manager.models.Note; |
8 |
| -import com.conveyal.datatools.manager.models.Project; |
| 5 | +import com.conveyal.datatools.manager.models.*; |
9 | 6 | import com.conveyal.datatools.manager.persistence.Persistence;
|
10 | 7 | import com.conveyal.datatools.manager.utils.json.JsonManager;
|
11 | 8 | import com.conveyal.datatools.manager.DataManager;
|
|
25 | 22 |
|
26 | 23 | import java.io.*;
|
27 | 24 | import java.net.URLEncoder;
|
| 25 | +import java.time.ZoneOffset; |
| 26 | +import java.time.ZonedDateTime; |
28 | 27 | import java.util.*;
|
29 | 28 |
|
30 | 29 | import com.conveyal.datatools.manager.auth.Auth0Users;
|
@@ -239,61 +238,164 @@ private static Object deleteUser(Request req, Response res) throws IOException {
|
239 | 238 |
|
240 | 239 | private static Object getRecentActivity(Request req, Response res) {
|
241 | 240 | Auth0UserProfile userProfile = req.attribute("user");
|
242 |
| - String from = req.queryParams("from"); |
243 |
| - String to = req.queryParams("to"); |
244 |
| -// if (from == null || to == null) { |
245 |
| -// halt(400, "Please provide valid from/to dates"); |
246 |
| -// } |
247 |
| - List<Activity> activity = new ArrayList<>(); |
| 241 | + |
| 242 | + /* TODO: Allow custom from/to range |
| 243 | + String fromStr = req.queryParams("from"); |
| 244 | + String toStr = req.queryParams("to"); */ |
| 245 | + |
| 246 | + // Default range: past 7 days |
| 247 | + ZonedDateTime from = ZonedDateTime.now(ZoneOffset.UTC).minusDays(7); |
| 248 | + ZonedDateTime to = ZonedDateTime.now(ZoneOffset.UTC); |
| 249 | + |
| 250 | + List<Activity> activityList = new ArrayList<>(); |
248 | 251 | Auth0UserProfile.DatatoolsInfo datatools = userProfile.getApp_metadata().getDatatoolsInfo();
|
249 |
| - if (datatools != null) { |
250 |
| - Auth0UserProfile.Subscription[] subscriptions = datatools.getSubscriptions(); |
251 |
| - if (subscriptions != null) { |
252 |
| - for (Auth0UserProfile.Subscription sub : subscriptions) { |
253 |
| - switch (sub.getType()) { |
254 |
| - // TODO: add all activity types |
255 |
| - case "feed-commented-on": |
256 |
| - for (String targetId : sub.getTarget()) { |
257 |
| - FeedSource fs = Persistence.feedSources.getById(targetId); |
258 |
| - if(fs == null) continue; |
259 |
| - for (Note note : fs.retrieveNotes()) { |
260 |
| - // TODO: Check if actually recent |
261 |
| -// if (note.date.after(Date.from(Instant.ofEpochSecond(from))) && note.date.before(Date.from(Instant.ofEpochSecond(to)))) { |
262 |
| - Activity act = new Activity(); |
263 |
| - act.type = sub.getType(); |
264 |
| - act.userId = note.userId; |
265 |
| - act.userName = note.userEmail; |
266 |
| - act.body = note.body; |
267 |
| - act.date = note.date; |
268 |
| - act.targetId = targetId; |
269 |
| - act.targetName = fs.name; |
270 |
| - activity.add(act); |
271 |
| -// } |
272 |
| - } |
| 252 | + if (datatools == null) { |
| 253 | + // NOTE: this condition will also occur if DISABLE_AUTH is set to true |
| 254 | + halt(403, SparkUtils.formatJSON("User does not have permission to access to this application", 403)); |
| 255 | + } |
| 256 | + |
| 257 | + Auth0UserProfile.Subscription[] subscriptions = datatools.getSubscriptions(); |
| 258 | + if (subscriptions == null) return activityList; |
| 259 | + |
| 260 | + /* NOTE: as of May-08-2018 we decided to limit subscriptions to two types: |
| 261 | + * 'feed-updated' and 'project-updated'. Comment subscriptions are now always |
| 262 | + * assumed if the containing 'feed-updated' subscription is active |
| 263 | + */ |
| 264 | + for (Auth0UserProfile.Subscription sub : subscriptions) { |
| 265 | + switch (sub.getType()) { |
| 266 | + case "feed-updated": |
| 267 | + for (String targetId : sub.getTarget()) { |
| 268 | + FeedSource fs = Persistence.feedSources.getById(targetId); |
| 269 | + if (fs == null) continue; |
| 270 | + |
| 271 | + // FeedSource comments |
| 272 | + for (Note note : fs.retrieveNotes()) { |
| 273 | + ZonedDateTime datePosted = toZonedDateTime(note.date); |
| 274 | + if (datePosted.isBefore(from) || datePosted.isAfter(to)) continue; |
| 275 | + activityList.add(new FeedSourceCommentActivity(note, fs)); |
| 276 | + } |
| 277 | + |
| 278 | + // Iterate through this Feed's FeedVersions |
| 279 | + for(FeedVersion version : fs.retrieveFeedVersions()) { |
| 280 | + // FeedVersion creation event |
| 281 | + ZonedDateTime dateCreated = toZonedDateTime(fs.dateCreated); |
| 282 | + if (dateCreated.isAfter(from) && dateCreated.isBefore(to)) { |
| 283 | + activityList.add(new FeedVersionCreationActivity(version, fs)); |
| 284 | + } |
| 285 | + |
| 286 | + // FeedVersion comments |
| 287 | + for (Note note : version.retrieveNotes()) { |
| 288 | + ZonedDateTime datePosted = toZonedDateTime(note.date); |
| 289 | + if (datePosted.isBefore(from) || datePosted.isAfter(to)) continue; |
| 290 | + activityList.add(new FeedVersionCommentActivity(note, fs, version)); |
273 | 291 | }
|
274 |
| - break; |
| 292 | + } |
| 293 | + } |
| 294 | + break; |
| 295 | + |
| 296 | + case "project-updated": |
| 297 | + // Iterate through Project IDs, skipping any that don't resolve to actual projects |
| 298 | + for (String targetId : sub.getTarget()) { |
| 299 | + Project proj = Persistence.projects.getById(targetId); |
| 300 | + if (proj == null) continue; |
| 301 | + |
| 302 | + // Iterate through Project's FeedSources, creating "Feed created" items as needed |
| 303 | + for (FeedSource fs : proj.retrieveProjectFeedSources()) { |
| 304 | + ZonedDateTime dateCreated = toZonedDateTime(fs.dateCreated); |
| 305 | + if (dateCreated.isBefore(from) || dateCreated.isAfter(to)) continue; |
| 306 | + activityList.add(new FeedSourceCreationActivity(fs, proj)); |
| 307 | + } |
275 | 308 | }
|
276 |
| - } |
| 309 | + break; |
277 | 310 | }
|
278 |
| - } else { |
279 |
| - // NOTE: this condition will also occur if DISABLE_AUTH is set to true |
280 |
| - halt(403, SparkUtils.formatJSON("User does not have permission to access to this application", 403)); |
281 | 311 | }
|
282 | 312 |
|
283 |
| - return activity; |
| 313 | + return activityList; |
284 | 314 | }
|
285 | 315 |
|
286 |
| - static class Activity implements Serializable { |
| 316 | + private static ZonedDateTime toZonedDateTime (Date date) { |
| 317 | + return ZonedDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC); |
| 318 | + } |
| 319 | + |
| 320 | + static abstract class Activity implements Serializable { |
287 | 321 | private static final long serialVersionUID = 1L;
|
288 | 322 | public String type;
|
289 | 323 | public String userId;
|
290 | 324 | public String userName;
|
291 |
| - public String body; |
292 |
| - public String targetId; |
293 |
| - public String targetName; |
294 | 325 | public Date date;
|
295 | 326 | }
|
296 | 327 |
|
| 328 | + static class FeedSourceCreationActivity extends Activity { |
| 329 | + public String feedSourceId; |
| 330 | + public String feedSourceName; |
| 331 | + public String projectId; |
| 332 | + public String projectName; |
| 333 | + |
| 334 | + public FeedSourceCreationActivity(FeedSource fs, Project proj) { |
| 335 | + this.type = "feed-created"; |
| 336 | + this.date = fs.dateCreated; |
| 337 | + this.userId = fs.userId; |
| 338 | + this.userName = fs.userEmail; |
| 339 | + this.feedSourceId = fs.id; |
| 340 | + this.feedSourceName = fs.name; |
| 341 | + this.projectId = proj.id; |
| 342 | + this.projectName = proj.name; |
| 343 | + } |
| 344 | + } |
| 345 | + |
| 346 | + static class FeedVersionCreationActivity extends Activity { |
| 347 | + public Integer feedVersionIndex; |
| 348 | + public String feedVersionName; |
| 349 | + public String feedSourceId; |
| 350 | + public String feedSourceName; |
| 351 | + |
| 352 | + public FeedVersionCreationActivity(FeedVersion version, FeedSource fs) { |
| 353 | + this.type = "version-created"; |
| 354 | + this.date = fs.dateCreated; |
| 355 | + this.userId = version.userId; |
| 356 | + this.userName = version.userEmail; |
| 357 | + this.feedVersionIndex = version.version; |
| 358 | + this.feedVersionName = version.name; |
| 359 | + this.feedSourceId = fs.id; |
| 360 | + this.feedSourceName = fs.name; |
| 361 | + } |
| 362 | + } |
| 363 | + |
| 364 | + static abstract class CommentActivity extends Activity { |
| 365 | + public String body; |
| 366 | + |
| 367 | + public CommentActivity (Note note) { |
| 368 | + this.date = note.date; |
| 369 | + this.userId = note.userId; |
| 370 | + this.userName = note.userEmail; |
| 371 | + this.body = note.body; |
| 372 | + } |
| 373 | + } |
| 374 | + |
| 375 | + static class FeedSourceCommentActivity extends CommentActivity { |
| 376 | + public String feedSourceId; |
| 377 | + public String feedSourceName; |
| 378 | + |
| 379 | + public FeedSourceCommentActivity(Note note, FeedSource feedSource) { |
| 380 | + super(note); |
| 381 | + this.type = "feed-commented-on"; |
| 382 | + this.feedSourceId = feedSource.id; |
| 383 | + this.feedSourceName = feedSource.name; |
| 384 | + } |
| 385 | + } |
| 386 | + |
| 387 | + static class FeedVersionCommentActivity extends FeedSourceCommentActivity { |
| 388 | + public Integer feedVersionIndex; |
| 389 | + public String feedVersionName; |
| 390 | + |
| 391 | + public FeedVersionCommentActivity(Note note, FeedSource feedSource, FeedVersion version) { |
| 392 | + super(note, feedSource); |
| 393 | + this.type = "version-commented-on"; |
| 394 | + this.feedVersionIndex = version.version; |
| 395 | + this.feedVersionName = version.name; |
| 396 | + } |
| 397 | + } |
| 398 | + |
297 | 399 | public static void register (String apiPrefix) {
|
298 | 400 | get(apiPrefix + "secure/user/:id", UserController::getUser, json::write);
|
299 | 401 | get(apiPrefix + "secure/user/:id/recentactivity", UserController::getRecentActivity, json::write);
|
|
0 commit comments