--- app/actions/AbstractProjectCheckAction.java
+++ app/actions/AbstractProjectCheckAction.java
... | ... | @@ -36,6 +36,7 @@ |
36 | 36 |
import utils.RedirectUtil; |
37 | 37 |
|
38 | 38 |
import static play.mvc.Controller.flash; |
39 |
+import static play.mvc.Http.Context.current; |
|
39 | 40 |
|
40 | 41 |
/** |
41 | 42 |
* Checks if the project which meets the request of a pattern, |
... | ... | @@ -49,9 +50,20 @@ |
49 | 50 |
public abstract class AbstractProjectCheckAction<T> extends Action<T> { |
50 | 51 |
@Override |
51 | 52 |
public final Promise<Result> call(Context context) throws Throwable { |
53 |
+ String ownerLoginId = null; |
|
54 |
+ String projectName = null; |
|
55 |
+ |
|
52 | 56 |
PathParser parser = new PathParser(context); |
53 |
- String ownerLoginId = parser.getOwnerLoginId(); |
|
54 |
- String projectName = parser.getProjectName(); |
|
57 |
+ if (current().request().getHeader(UserApp.USER_TOKEN_HEADER) != null) { |
|
58 |
+ // eg. context.request().path() : /-_-api/v1/owners/doortts/projects/Test/posts |
|
59 |
+ String[] base = context.request().path().split("/owners/"); |
|
60 |
+ String[] partial = base[1].split("/"); |
|
61 |
+ ownerLoginId = partial[0]; |
|
62 |
+ projectName = partial[2]; |
|
63 |
+ } else { |
|
64 |
+ ownerLoginId = parser.getOwnerLoginId(); |
|
65 |
+ projectName = parser.getProjectName(); |
|
66 |
+ } |
|
55 | 67 |
|
56 | 68 |
Project project = Project.findByOwnerAndProjectName(ownerLoginId, projectName); |
57 | 69 |
|
--- app/controllers/AbstractPostingApp.java
+++ app/controllers/AbstractPostingApp.java
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 |
*/ |
21 | 21 |
package controllers; |
22 | 22 |
|
23 |
+import com.fasterxml.jackson.databind.JsonNode; |
|
23 | 24 |
import controllers.annotation.AnonymousCheck; |
24 | 25 |
import models.*; |
25 | 26 |
import models.enumeration.Direction; |
... | ... | @@ -135,6 +136,23 @@ |
135 | 136 |
} |
136 | 137 |
} |
137 | 138 |
|
139 |
+ public static void attachUploadFilesToPost(JsonNode files, Resource resource) { |
|
140 |
+ if(files.isArray() && files.size() > 0){ |
|
141 |
+ String [] fileIds = new String[files.size()]; |
|
142 |
+ int idx = 0; |
|
143 |
+ for (JsonNode fileNo : files) { |
|
144 |
+ fileIds[idx] = fileNo.asText(); |
|
145 |
+ idx++; |
|
146 |
+ } |
|
147 |
+ int attachedFileCount = Attachment.moveOnlySelected(UserApp.currentUser().asResource(), resource, |
|
148 |
+ fileIds); |
|
149 |
+ if( attachedFileCount != files.size()){ |
|
150 |
+ flash(Constants.TITLE, Messages.get("post.popup.fileAttach.hasMissing", files.size() - attachedFileCount)); |
|
151 |
+ flash(Constants.DESCRIPTION, Messages.get("post.popup.fileAttach.hasMissing.description", getTemporaryFilesServerKeepUpTimeOfMinuntes())); |
|
152 |
+ } |
|
153 |
+ } |
|
154 |
+ } |
|
155 |
+ |
|
138 | 156 |
private static long getTemporaryFilesServerKeepUpTimeOfMinuntes() { |
139 | 157 |
return AttachmentApp.TEMPORARYFILES_KEEPUP_TIME_MILLIS/(60*1000l); |
140 | 158 |
} |
--- app/controllers/AttachmentApp.java
+++ app/controllers/AttachmentApp.java
... | ... | @@ -62,7 +62,10 @@ |
62 | 62 |
} |
63 | 63 |
File file = filePart.getFile(); |
64 | 64 |
|
65 |
- User uploader = accessedWithToken(request().getHeader("Yona-Token")); |
|
65 |
+ User uploader = UserApp.currentUser(); |
|
66 |
+ if (uploader.isAnonymous()) { |
|
67 |
+ uploader = User.findByUserToken(request().getHeader("Yona-Token")); |
|
68 |
+ } |
|
66 | 69 |
|
67 | 70 |
// Anonymous cannot upload a file. |
68 | 71 |
if (uploader.isAnonymous()) { |
... | ... | @@ -117,19 +120,6 @@ |
117 | 120 |
// Why not 204? Because 204 doesn't allow response to have a body, |
118 | 121 |
// so we cannot tell what is same with the file you try to add. |
119 | 122 |
return ok(responseBody); |
120 |
- } |
|
121 |
- } |
|
122 |
- |
|
123 |
- private static User accessedWithToken(String token){ |
|
124 |
- User user = null; |
|
125 |
- if(token != null) { |
|
126 |
- user = User.find.where().eq("token", token).findUnique(); |
|
127 |
- } |
|
128 |
- |
|
129 |
- if(user == null){ |
|
130 |
- return User.anonymous; |
|
131 |
- } else { |
|
132 |
- return user; |
|
133 | 123 |
} |
134 | 124 |
} |
135 | 125 |
|
--- app/controllers/BoardApi.java
+++ app/controllers/BoardApi.java
... | ... | @@ -9,13 +9,16 @@ |
9 | 9 |
|
10 | 10 |
import com.fasterxml.jackson.databind.JsonNode; |
11 | 11 |
import com.fasterxml.jackson.databind.node.ObjectNode; |
12 |
-import models.IssueLabel; |
|
13 |
-import models.Posting; |
|
14 |
-import models.Project; |
|
12 |
+import controllers.annotation.IsCreatable; |
|
13 |
+import models.*; |
|
14 |
+import models.enumeration.ResourceType; |
|
15 |
+import org.joda.time.DateTime; |
|
15 | 16 |
import play.db.ebean.Transactional; |
16 | 17 |
import play.libs.Json; |
17 | 18 |
import play.mvc.Result; |
19 |
+import utils.JodaDateUtil; |
|
18 | 20 |
|
21 |
+import java.util.Date; |
|
19 | 22 |
import java.util.HashSet; |
20 | 23 |
import java.util.Set; |
21 | 24 |
|
... | ... | @@ -34,7 +37,6 @@ |
34 | 37 |
Set<IssueLabel> labels = new HashSet<>(); |
35 | 38 |
|
36 | 39 |
for(JsonNode node: json){ |
37 |
- System.out.println("node: " + node); |
|
38 | 40 |
Long labelId = Long.parseLong(node.asText()); |
39 | 41 |
labels.add(IssueLabel.finder.byId(labelId)); |
40 | 42 |
} |
... | ... | @@ -48,4 +50,42 @@ |
48 | 50 |
return ok(result); |
49 | 51 |
} |
50 | 52 |
|
53 |
+ @Transactional |
|
54 |
+ @IsCreatable(ResourceType.BOARD_POST) |
|
55 |
+ public static Result newPostByJson(String owner, String projectName) { |
|
56 |
+ ObjectNode result = Json.newObject(); |
|
57 |
+ JsonNode json = request().body().asJson(); |
|
58 |
+ if(json == null) { |
|
59 |
+ return badRequest("Expecting Json data"); |
|
60 |
+ } |
|
61 |
+ |
|
62 |
+ Project project = Project.findByOwnerAndProjectName(owner, projectName); |
|
63 |
+ |
|
64 |
+ User user = User.findUserIfTokenExist(UserApp.currentUser()); |
|
65 |
+ JsonNode files = json.findValue("temporaryUploadFiles"); |
|
66 |
+ |
|
67 |
+ final Posting post = new Posting(); |
|
68 |
+ |
|
69 |
+ post.createdDate = getCreatedDate(json.findValue("created").asLong()); |
|
70 |
+ post.updatedDate = getCreatedDate(json.findValue("created").asLong()); |
|
71 |
+ post.setAuthor(user); |
|
72 |
+ post.project = project; |
|
73 |
+ post.title = json.findValue("title").asText(); |
|
74 |
+ post.body = json.findValue("body").asText(); |
|
75 |
+ if(json.findValue("id") != null && json.findValue("id").asLong() > 0){ |
|
76 |
+ post.saveWithNumber(json.findValue("id").asLong()); |
|
77 |
+ } else { |
|
78 |
+ post.save(); |
|
79 |
+ } |
|
80 |
+ attachUploadFilesToPost(files, post.asResource()); |
|
81 |
+ |
|
82 |
+ return ok(result); |
|
83 |
+ } |
|
84 |
+ |
|
85 |
+ private static Date getCreatedDate(long timestamp){ |
|
86 |
+ if(timestamp == 0){ |
|
87 |
+ return JodaDateUtil.now(); |
|
88 |
+ } |
|
89 |
+ return new DateTime(timestamp * 1000).toDate(); |
|
90 |
+ } |
|
51 | 91 |
} |
--- app/controllers/UserApp.java
+++ app/controllers/UserApp.java
... | ... | @@ -70,6 +70,7 @@ |
70 | 70 |
public static final String DEFAULT_GROUP = "own"; |
71 | 71 |
public static final String DEFAULT_SELECTED_TAB = "projects"; |
72 | 72 |
public static final String TOKEN_USER = "TOKEN_USER"; |
73 |
+ public static final String USER_TOKEN_HEADER = "Yona-Token"; |
|
73 | 74 |
|
74 | 75 |
@AnonymousCheck |
75 | 76 |
public static Result users(String query) { |
... | ... | @@ -361,6 +362,11 @@ |
361 | 362 |
User user = getUserFromSession(); |
362 | 363 |
if (!user.isAnonymous()) { |
363 | 364 |
return user; |
365 |
+ } else { |
|
366 |
+ user = User.findUserIfTokenExist(user); |
|
367 |
+ } |
|
368 |
+ if(!user.isAnonymous()) { |
|
369 |
+ return user; |
|
364 | 370 |
} |
365 | 371 |
return getUserFromContext(); |
366 | 372 |
} |
--- app/models/AbstractPosting.java
+++ app/models/AbstractPosting.java
... | ... | @@ -143,6 +143,14 @@ |
143 | 143 |
} |
144 | 144 |
|
145 | 145 |
@Transactional |
146 |
+ public void saveWithNumber(long number) { |
|
147 |
+ this.number = number; |
|
148 |
+ numOfComments = computeNumOfComments(); |
|
149 |
+ super.save(); |
|
150 |
+ updateMention(); |
|
151 |
+ } |
|
152 |
+ |
|
153 |
+ @Transactional |
|
146 | 154 |
public void update() { |
147 | 155 |
numOfComments = computeNumOfComments(); |
148 | 156 |
super.update(); |
--- app/models/Attachment.java
+++ app/models/Attachment.java
... | ... | @@ -84,11 +84,15 @@ |
84 | 84 |
* @return an attachment which matches up with the given one. |
85 | 85 |
*/ |
86 | 86 |
private static Attachment findBy(Attachment attach) { |
87 |
- return find.where() |
|
87 |
+ List<Attachment> list = find.where() |
|
88 | 88 |
.eq("name", attach.name) |
89 | 89 |
.eq("hash", attach.hash) |
90 | 90 |
.eq("containerType", attach.containerType) |
91 |
- .eq("containerId", attach.containerId).findUnique(); |
|
91 |
+ .eq("containerId", attach.containerId).findList(); |
|
92 |
+ if( list.size() > 0) { |
|
93 |
+ return list.get(0); |
|
94 |
+ } |
|
95 |
+ return null; |
|
92 | 96 |
} |
93 | 97 |
|
94 | 98 |
/** |
--- app/models/User.java
+++ app/models/User.java
... | ... | @@ -275,6 +275,30 @@ |
275 | 275 |
} |
276 | 276 |
} |
277 | 277 |
|
278 |
+ public static User findByUserToken(String token){ |
|
279 |
+ User user = null; |
|
280 |
+ if(token != null) { |
|
281 |
+ user = User.find.where().eq("token", token).findUnique(); |
|
282 |
+ } |
|
283 |
+ |
|
284 |
+ if(user != null){ |
|
285 |
+ return user; |
|
286 |
+ } |
|
287 |
+ |
|
288 |
+ return User.anonymous; |
|
289 |
+ } |
|
290 |
+ |
|
291 |
+ public static User findUserIfTokenExist(User user){ |
|
292 |
+ if(!user.isAnonymous()){ |
|
293 |
+ return user; |
|
294 |
+ } |
|
295 |
+ String userToken = play.mvc.Http.Context.current().request().getHeader(UserApp.USER_TOKEN_HEADER); |
|
296 |
+ if( userToken != null) { |
|
297 |
+ return User.findByUserToken(userToken); |
|
298 |
+ } |
|
299 |
+ return User.anonymous; |
|
300 |
+ } |
|
301 |
+ |
|
278 | 302 |
/** |
279 | 303 |
* |
280 | 304 |
* Find a user by email account. |
--- app/utils/AccessControl.java
+++ app/utils/AccessControl.java
... | ... | @@ -58,6 +58,7 @@ |
58 | 58 |
* @return true if the user has the permission |
59 | 59 |
*/ |
60 | 60 |
public static boolean isProjectResourceCreatable(User user, Project project, ResourceType resourceType) { |
61 |
+ user = User.findUserIfTokenExist(user); |
|
61 | 62 |
// Anonymous user cannot create anything. |
62 | 63 |
if (user == null || user.isAnonymous()) { |
63 | 64 |
return false; |
--- app/utils/HttpUtil.java
+++ app/utils/HttpUtil.java
... | ... | @@ -74,8 +74,7 @@ |
74 | 74 |
* |
75 | 75 |
* @param request the request of the client |
76 | 76 |
* @param types the supported types |
77 |
- * @return the most preferred type; {@code null} if the client has no |
|
78 |
- * preference among the supported types. |
|
77 |
+ * @return the most preferred type; |
|
79 | 78 |
*/ |
80 | 79 |
public static String getPreferType(Http.Request request, String ... types) { |
81 | 80 |
// acceptedTypes is sorted by preference. |
... | ... | @@ -86,7 +85,7 @@ |
86 | 85 |
} |
87 | 86 |
} |
88 | 87 |
} |
89 |
- return null; |
|
88 |
+ return "text/html"; // Default fallback. Should not be null! |
|
90 | 89 |
} |
91 | 90 |
|
92 | 91 |
/** |
--- build.sbt
+++ build.sbt
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 |
"com.h2database" % "h2" % "1.3.176", |
17 | 17 |
// JDBC driver for mariadb |
18 | 18 |
"org.mariadb.jdbc" % "mariadb-java-client" % "1.3.6", |
19 |
+ "net.contentobjects.jnotify" % "jnotify" % "0.94", |
|
19 | 20 |
// Core Library |
20 | 21 |
"org.eclipse.jgit" % "org.eclipse.jgit" % "3.5.3.201412180710-r", |
21 | 22 |
// Smart HTTP Servlet |
--- conf/routes
+++ conf/routes
... | ... | @@ -23,7 +23,8 @@ |
23 | 23 |
|
24 | 24 |
GET /-_-api controllers.Application.index() |
25 | 25 |
GET /-_-api/v1/ controllers.Application.index() |
26 |
-POST /-_-api/v1/owners/:owner/projects/:projectName/:number controllers.BoardApi.updatePostLabel(owner:String, projectName:String, number:Long) |
|
26 |
+POST /-_-api/v1/owners/:owner/projects/:projectName/posts controllers.BoardApi.newPostByJson(owner:String, projectName:String) |
|
27 |
+POST /-_-api/v1/owners/:owner/projects/:projectName/postlabel/:number controllers.BoardApi.updatePostLabel(owner:String, projectName:String, number:Long) |
|
27 | 28 |
|
28 | 29 |
# Import |
29 | 30 |
GET /import controllers.ImportApp.importForm() |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?