Skip to content

Commit c3b7725

Browse files
committed
For great justice.
0 parents  commit c3b7725

29 files changed

+1527
-0
lines changed

.gitignore

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
logs
2+
project/project
3+
project/target
4+
target
5+
tmp
6+
.history
7+
dist
8+
/.idea
9+
/*.iml
10+
/out
11+
/.idea_modules
12+
/.classpath
13+
/.project
14+
/RUNNING_PID
15+
/.settings

README

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
This is your new Play 2.1 application
2+
=====================================
3+
4+
This file will be packaged with your application, when using `play dist`.

app/Global.java

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import com.google.inject.Guice;
2+
import com.google.inject.Injector;
3+
import play.Application;
4+
import play.GlobalSettings;
5+
import services.PlayModule;
6+
7+
public class Global extends GlobalSettings {
8+
private Application application;
9+
private Injector injector;
10+
11+
@Override
12+
public void onStart(Application application) {
13+
this.application = application;
14+
injector = Guice.createInjector(new PlayModule(application));
15+
}
16+
17+
@Override
18+
public void onStop(Application application) {
19+
this.application = null;
20+
this.injector = null;
21+
}
22+
23+
@Override
24+
public <A> A getControllerInstance(Class<A> aClass) throws Exception {
25+
return injector.getInstance(aClass);
26+
}
27+
}

app/controllers/Application.java

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package controllers;
2+
3+
import play.*;
4+
import play.core.Router;
5+
import play.mvc.*;
6+
7+
import views.html.*;
8+
9+
import java.lang.reflect.Method;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
13+
public class Application extends Controller {
14+
15+
public static Result index(String path) {
16+
return ok(index.render());
17+
}
18+
19+
public static Result router() throws Exception {
20+
return ok(getJavascriptReverseRouter()).as("text/javascript");
21+
}
22+
23+
24+
private static String javascriptReverseRouter;
25+
26+
private static String getJavascriptReverseRouter() throws Exception {
27+
if (javascriptReverseRouter == null) {
28+
List<Router.JavascriptReverseRoute> javascriptRoutes = new ArrayList<>();
29+
javascriptRoutes.addAll(scanRouter(routes.javascript.UserController));
30+
javascriptRoutes.addAll(scanRouter(routes.javascript.FeedController));
31+
javascriptReverseRouter = Routes.javascriptRouter("routes", javascriptRoutes.toArray(new Router.JavascriptReverseRoute[0]));
32+
}
33+
return javascriptReverseRouter;
34+
}
35+
36+
private static List<Router.JavascriptReverseRoute> scanRouter(Object router) throws Exception {
37+
List<Router.JavascriptReverseRoute> routes = new ArrayList<>();
38+
for (Method method: router.getClass().getMethods()) {
39+
if (method.getParameterTypes().length == 0 &&
40+
Router.JavascriptReverseRoute.class.isAssignableFrom(method.getReturnType())) {
41+
routes.add(Router.JavascriptReverseRoute.class.cast(method.invoke(router)));
42+
}
43+
}
44+
return routes;
45+
}
46+
47+
}

app/controllers/FeedController.java

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package controllers;
2+
3+
import models.StatusUpdate;
4+
import play.libs.Json;
5+
import play.mvc.Controller;
6+
import play.mvc.Result;
7+
import play.mvc.Security;
8+
import services.FeedDao;
9+
import services.UserDao;
10+
11+
import javax.inject.Inject;
12+
import javax.inject.Singleton;
13+
import java.util.*;
14+
15+
@Singleton
16+
public class FeedController extends Controller {
17+
18+
private final FeedDao feedDao;
19+
private final UserDao userDao;
20+
21+
@Inject
22+
public FeedController(FeedDao feedDao, UserDao userDao) {
23+
this.feedDao = feedDao;
24+
this.userDao = userDao;
25+
}
26+
27+
@Security.Authenticated
28+
public Result getFeed() {
29+
// Get followers
30+
List<String> following = new ArrayList<>(userDao.get(request().username()).getFollowing());
31+
following.add(request().username());
32+
33+
// Get updates
34+
List<StatusUpdate> updates = feedDao.getFeed(following);
35+
36+
// Create map of user ids to users
37+
List<UserController.UserView> users = UserController.UserView.fromUsers(userDao.get(following));
38+
Map<String, UserController.UserView> userMap = new HashMap<>();
39+
for (UserController.UserView user: users) {
40+
userMap.put(user.id, user);
41+
}
42+
43+
// Create feed
44+
List<StatusUpdateView> feed = new ArrayList<>();
45+
for (StatusUpdate update: updates) {
46+
StatusUpdateView view = StatusUpdateView.fromStatusUpdate(update);
47+
view.user = userMap.get(update.getUser());
48+
feed.add(view);
49+
}
50+
return ok(Json.toJson(feed));
51+
}
52+
53+
public Result getFeedForUser(String id) {
54+
List<StatusUpdateView> feed = new ArrayList<>();
55+
UserController.UserView userView = UserController.UserView.fromUser(userDao.get(id));
56+
57+
for (StatusUpdate update: feedDao.getFeed(id)) {
58+
StatusUpdateView view = StatusUpdateView.fromStatusUpdate(update);
59+
view.user = userView;
60+
feed.add(view);
61+
}
62+
63+
return ok(Json.toJson(feed));
64+
}
65+
66+
@Security.Authenticated
67+
public Result like(String id) {
68+
feedDao.like(id, request().username());
69+
return noContent();
70+
}
71+
72+
@Security.Authenticated
73+
public Result unlike(String id) {
74+
feedDao.unlike(id, request().username());
75+
return noContent();
76+
}
77+
78+
@Security.Authenticated
79+
public Result updateStatus() {
80+
String text = request().body().asJson().get("status").asText();
81+
feedDao.save(new StatusUpdate(request().username(), text));
82+
return noContent();
83+
}
84+
85+
public Result trending() {
86+
return ok(Json.toJson(feedDao.trending()));
87+
}
88+
89+
public static class StatusUpdateView {
90+
public String id;
91+
public UserController.UserView user;
92+
public Date date;
93+
public String text;
94+
public List<String> likes;
95+
96+
public static StatusUpdateView fromStatusUpdate(StatusUpdate update) {
97+
StatusUpdateView view = new StatusUpdateView();
98+
view.id = update.getId();
99+
view.date = update.getDate();
100+
view.text = update.getText();
101+
view.likes = update.getLikes();
102+
return view;
103+
}
104+
}
105+
}

app/controllers/UserController.java

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package controllers;
2+
3+
import models.User;
4+
import org.apache.commons.codec.digest.DigestUtils;
5+
import play.libs.Crypto;
6+
import play.mvc.Security;
7+
import services.UserDao;
8+
import org.apache.commons.codec.binary.Base64;
9+
import org.mindrot.jbcrypt.BCrypt;
10+
import play.libs.Json;
11+
import play.mvc.Controller;
12+
import play.mvc.Result;
13+
14+
import javax.inject.Inject;
15+
import javax.inject.Singleton;
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
19+
@Singleton
20+
public class UserController extends Controller {
21+
private final UserDao userDao;
22+
23+
@Inject
24+
public UserController(UserDao userDao) {
25+
this.userDao = userDao;
26+
}
27+
28+
public Result getUser(String id) {
29+
User user = userDao.get(id);
30+
if (user == null) {
31+
return notFound();
32+
}
33+
List<User> following = userDao.get(user.getFollowing());
34+
List<User> followers = userDao.get(user.getFollowers());
35+
UserView view = UserView.fromUser(user);
36+
view.followers = UserView.fromUsers(followers);
37+
view.following = UserView.fromUsers(following);
38+
return ok(Json.toJson(view));
39+
}
40+
41+
public Result newUser() {
42+
UserSignup signup = Json.fromJson(request().body().asJson(), UserSignup.class);
43+
if (userDao.findByEmail(signup.email) != null) {
44+
return badRequest();
45+
}
46+
User user = new User(signup.email, signup.name, BCrypt.hashpw(signup.password, BCrypt.gensalt()));
47+
User newUser = userDao.create(user);
48+
session().put("username", newUser.getId());
49+
response().setHeader(LOCATION, routes.UserController.getUser(newUser.getId()).url());
50+
return created();
51+
}
52+
53+
public Result signIn() {
54+
UserSignup signup = Json.fromJson(request().body().asJson(), UserSignup.class);
55+
User user = userDao.findByEmail(signup.email);
56+
if (user == null) {
57+
return notFound();
58+
}
59+
if (BCrypt.checkpw(signup.password, user.getPasswordHash())) {
60+
session().put("username", user.getId());
61+
return getUser(user.getId());
62+
} else {
63+
return notFound();
64+
}
65+
}
66+
67+
@Security.Authenticated
68+
public Result current() {
69+
return getUser(request().username());
70+
}
71+
72+
public Result search(String term) {
73+
return ok(Json.toJson(UserView.fromUsers(userDao.search(term))));
74+
}
75+
76+
public Result logOut() {
77+
session().clear();
78+
return ok();
79+
}
80+
81+
@Security.Authenticated
82+
public Result followUser(String id) {
83+
if (userDao.get(id) == null) {
84+
return notFound();
85+
}
86+
userDao.follow(request().username(), id);
87+
return ok();
88+
}
89+
90+
@Security.Authenticated
91+
public Result unfollowUser(String id) {
92+
userDao.unfollow(request().username(), id);
93+
return ok();
94+
}
95+
96+
public static class UserSignup {
97+
public String name;
98+
public String email;
99+
public String password;
100+
}
101+
102+
public static class UserView {
103+
public String id;
104+
public String name;
105+
public String gravatar;
106+
public int updates;
107+
public List<UserView> followers;
108+
public List<UserView> following;
109+
110+
static List<UserView> fromUsers(List<User> users) {
111+
List<UserView> views = new ArrayList<UserView>(users.size());
112+
for (User user: users) {
113+
views.add(fromUser(user));
114+
}
115+
return views;
116+
}
117+
118+
static UserView fromUser(User user) {
119+
UserView view = new UserView();
120+
view.id = user.getId();
121+
view.name = user.getName();
122+
view.gravatar = "//www.gravatar.com/avatar/" + DigestUtils.md5Hex(user.getEmail());
123+
view.updates = user.getUpdates();
124+
return view;
125+
}
126+
}
127+
128+
}
129+

app/models/StatusUpdate.java

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package models;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import org.mongojack.Id;
6+
import org.mongojack.ObjectId;
7+
8+
import java.util.ArrayList;
9+
import java.util.Date;
10+
import java.util.List;
11+
12+
public class StatusUpdate {
13+
private final String id;
14+
private final String user;
15+
private final Date date;
16+
private final String text;
17+
private final List<String> likes;
18+
19+
@JsonCreator
20+
public StatusUpdate(
21+
@Id @ObjectId String id,
22+
@JsonProperty("user") @ObjectId String user,
23+
@JsonProperty("date") Date date,
24+
@JsonProperty("text") String text,
25+
@JsonProperty("likes") @ObjectId List<String> likes) {
26+
this.id = id;
27+
this.user = user;
28+
this.date = date;
29+
this.text = text;
30+
this.likes = likes;
31+
}
32+
33+
public StatusUpdate(String userId, String text) {
34+
this(null, userId, new Date(), text, new ArrayList<String>());
35+
}
36+
37+
@Id
38+
@ObjectId
39+
public String getId() {
40+
return id;
41+
}
42+
43+
@ObjectId
44+
public String getUser() {
45+
return user;
46+
}
47+
48+
public Date getDate() {
49+
return date;
50+
}
51+
52+
public String getText() {
53+
return text;
54+
}
55+
56+
@ObjectId
57+
public List<String> getLikes() {
58+
return likes;
59+
}
60+
61+
}

0 commit comments

Comments
 (0)