Unverified Commit 069d290b authored by zauberstuhl's avatar zauberstuhl Committed by GitHub

Merge pull request #2 from ganggo/refactor_dispatcher_receiver_jobs

Refactor dispatcher receiver jobs
parents 5b6116bf ea43034f
...@@ -158,14 +158,8 @@ func (a ApiAspect) CreatePerson() revel.Result { ...@@ -158,14 +158,8 @@ func (a ApiAspect) CreatePerson() revel.Result {
PersonID: personID, PersonID: personID,
} }
err := membership.Create()
if err != nil {
a.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return a.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
var person models.Person var person models.Person
err = person.FindByID(personID) err := person.FindByID(personID)
if err != nil { if err != nil {
a.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND) a.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return a.ApiError(http.StatusNotFound, ERR_NOT_FOUND) return a.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
...@@ -182,6 +176,11 @@ func (a ApiAspect) CreatePerson() revel.Result { ...@@ -182,6 +176,11 @@ func (a ApiAspect) CreatePerson() revel.Result {
} }
go dispatcher.Run() go dispatcher.Run()
err = membership.Create()
if err != nil {
a.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return a.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
return a.RenderJSON(membership) return a.RenderJSON(membership)
} }
......
...@@ -31,6 +31,9 @@ const ( ...@@ -31,6 +31,9 @@ const (
ERR_PASSWORD = "Password did not match" ERR_PASSWORD = "Password did not match"
ERR_UNAUTHORIZED = "You are not authenticated" ERR_UNAUTHORIZED = "You are not authenticated"
ERR_SERVER = "Internal server error" ERR_SERVER = "Internal server error"
ERR_USER_NOT_FOUND = "User not found"
ERR_POST_NOT_FOUND = "Post not found"
ERR_BAD_REQUEST = "Bad request"
ERR_NOT_FOUND = "Not found" ERR_NOT_FOUND = "Not found"
ERR_NOT_IMPLEMENTED = "Not implemented" ERR_NOT_IMPLEMENTED = "Not implemented"
) )
......
...@@ -22,6 +22,8 @@ import ( ...@@ -22,6 +22,8 @@ import (
"gopkg.in/ganggo/ganggo.v0/app/models" "gopkg.in/ganggo/ganggo.v0/app/models"
"gopkg.in/ganggo/ganggo.v0/app/jobs" "gopkg.in/ganggo/ganggo.v0/app/jobs"
"gopkg.in/ganggo/api.v0/app/helpers" "gopkg.in/ganggo/api.v0/app/helpers"
// XXX only for uuid
uuid "gopkg.in/ganggo/ganggo.v0/app/helpers"
federation "gopkg.in/ganggo/federation.v0" federation "gopkg.in/ganggo/federation.v0"
"strconv" "strconv"
"net/http" "net/http"
...@@ -209,16 +211,16 @@ func (c ApiComment) IndexPost() revel.Result { ...@@ -209,16 +211,16 @@ func (c ApiComment) IndexPost() revel.Result {
*/ */
func (c ApiComment) CreatePost() revel.Result { func (c ApiComment) CreatePost() revel.Result {
var ( var (
comment, fields string text, fields string
postID uint postID uint
post models.Post post models.Post
) )
c.Params.Bind(&comment, "comment") c.Params.Bind(&text, "comment")
c.Params.Bind(&fields, "fields") c.Params.Bind(&fields, "fields")
c.Params.Bind(&postID, "id") c.Params.Bind(&postID, "id")
if helpers.EmptyString(comment) { if helpers.EmptyString(text) {
c.Log.Error(TAG, "api", ERR_EMPTY_STRING) c.Log.Error(TAG, "api", ERR_EMPTY_STRING)
return c.ApiError(http.StatusBadRequest, ERR_EMPTY_STRING) return c.ApiError(http.StatusBadRequest, ERR_EMPTY_STRING)
} }
...@@ -228,20 +230,111 @@ func (c ApiComment) CreatePost() revel.Result { ...@@ -228,20 +230,111 @@ func (c ApiComment) CreatePost() revel.Result {
return c.ApiError(http.StatusNotFound, ERR_NOT_FOUND) return c.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
} }
guid, err := uuid.Uuid()
if err != nil {
c.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return c.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entityComment := federation.EntityComment{
Author: c.CurrentUser.Person.Author,
Guid: guid,
ParentGuid: post.Guid,
Text: text,
}
var comment models.Comment
err = comment.Create(&entityComment)
if err != nil {
c.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return c.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entityComment.CreatedAt = federation.Time{
Time: comment.CreatedAt,
}
dispatcher := jobs.Dispatcher{ dispatcher := jobs.Dispatcher{
User: c.CurrentUser, User: c.CurrentUser,
ParentPerson: &post.Person, Model: comment,
Message: federation.EntityComment{ Message: entityComment,
ParentGuid: post.Guid,
Text: comment,
},
} }
// XXX
// notify local user about a new comment
//go like.TriggerNotification(parentUser)
// deliver to the network
go dispatcher.Run() go dispatcher.Run()
// XXX that should return the comment return c.RenderJSON(comment)
return c.RenderJSON(post)
} }
func (c ApiComment) Delete() revel.Result { /**
return c.NotFound("Not implemented yet") * @api {delete} /comments/:guid Delete a comment
* @apiName ApiComment.Delete
* @apiGroup Comments
*
* @apiParam {String} access_token Oauth access token
* @apiParam {String} guid Unique global ID
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {}
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} BadRequest
* HTTP/1.1 400 BadRequest
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
*/
func (c ApiComment) Delete(guid string) revel.Result {
var comment models.Comment
commentID, err := strconv.ParseUint(guid, 10, 32);
if err == nil {
err = comment.FindByUserAndID(c.CurrentUser, uint(commentID))
} else {
err = comment.FindByUserAndGuid(c.CurrentUser, guid)
}
if err != nil {
c.Log.Error(TAG, "db", err, "api", ERR_POST_NOT_FOUND)
return c.ApiError(http.StatusNotFound, ERR_POST_NOT_FOUND)
}
if comment.Person.ID == c.CurrentUser.Person.ID {
entity := federation.EntityRetraction{
Author: c.CurrentUser.Person.Author,
TargetGuid: comment.Guid,
TargetType: models.ShareableComment,
}
dispatcher := jobs.Dispatcher{Message: entity}
// NOTE relay to other hosts if we own this entity
// should be done before we start deleting db records
// thats why this call is synchron XXX we should
// change that !
dispatcher.Run()
err = comment.Delete()
if err != nil {
c.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return c.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
} else {
c.Log.Error(TAG, "api", ERR_BAD_REQUEST)
return c.ApiError(http.StatusBadRequest, ERR_BAD_REQUEST)
}
return c.RenderJSON(struct{}{})
} }
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"gopkg.in/ganggo/ganggo.v0/app/helpers" "gopkg.in/ganggo/ganggo.v0/app/helpers"
federation "gopkg.in/ganggo/federation.v0" federation "gopkg.in/ganggo/federation.v0"
"net/http" "net/http"
"strconv"
) )
/** /**
...@@ -185,7 +186,7 @@ func (l ApiLike) Create() revel.Result { ...@@ -185,7 +186,7 @@ func (l ApiLike) Create() revel.Result {
Positive: positive, Positive: positive,
Guid: guid, Guid: guid,
Author: l.CurrentUser.Person.Author, Author: l.CurrentUser.Person.Author,
TargetType: models.ShareablePost, ParentType: models.ShareablePost,
ParentGuid: post.Guid, ParentGuid: post.Guid,
} }
...@@ -197,25 +198,93 @@ func (l ApiLike) Create() revel.Result { ...@@ -197,25 +198,93 @@ func (l ApiLike) Create() revel.Result {
dispatcher := jobs.Dispatcher{ dispatcher := jobs.Dispatcher{
User: l.CurrentUser, User: l.CurrentUser,
Model: like,
Message: entityLike, Message: entityLike,
} }
if parentUser, ok := like.ParentIsLocal(); ok { // XXX
dispatcher.ParentUser = &parentUser
// notify local user about a new comment // notify local user about a new comment
go like.TriggerNotification(parentUser) //go like.TriggerNotification(parentUser)
}
// deliver to the network // deliver to the network
go dispatcher.Run() go dispatcher.Run()
return l.RenderJSON(like) return l.RenderJSON(like)
} }
func (l ApiLike) Show() revel.Result { /**
return l.NotFound("Not implemented yet") * @api {delete} /likes/:guid Delete a like
} * @apiName ApiLike.Delete
* @apiGroup Likes
*
* @apiParam {String} access_token Oauth access token
* @apiParam {String} guid Unique global ID
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {}
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} BadRequest
* HTTP/1.1 400 BadRequest
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
*/
func (l ApiLike) Delete(guid string) revel.Result {
var post models.Post
postID, err := strconv.ParseUint(guid, 10, 32);
if err == nil {
err = post.FindByIDAndUser(uint(postID), l.CurrentUser)
} else {
err = post.FindByGuidAndUser(guid, l.CurrentUser)
}
if err != nil {
l.Log.Error(TAG, "db", err, "api", ERR_POST_NOT_FOUND)
return l.ApiError(http.StatusNotFound, ERR_POST_NOT_FOUND)
}
func (l ApiLike) Delete() revel.Result { var like models.Like
return l.NotFound("Not implemented yet") err = like.FindByUserAndPostID(l.CurrentUser, post.ID)
if err != nil {
l.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return l.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
if like.PersonID == l.CurrentUser.Person.ID {
entity := federation.EntityRetraction{
Author: l.CurrentUser.Person.Author,
TargetGuid: like.Guid,
TargetType: models.ShareableLike,
}
dispatcher := jobs.Dispatcher{Message: entity}
// NOTE relay to other hosts if we own this entity
// should be done before we start deleting db records
// thats why this call is synchron XXX we should
// change that !
dispatcher.Run()
err = like.Delete()
if err != nil {
l.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return l.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
} else {
l.Log.Error(TAG, "api", ERR_BAD_REQUEST)
return l.ApiError(http.StatusBadRequest, ERR_BAD_REQUEST)
}
return l.RenderJSON(struct{}{})
} }
...@@ -195,7 +195,7 @@ func (p ApiPost) Create() revel.Result { ...@@ -195,7 +195,7 @@ func (p ApiPost) Create() revel.Result {
Text: postText, Text: postText,
Author: p.CurrentUser.Person.Author, Author: p.CurrentUser.Person.Author,
Guid: guid, Guid: guid,
CreatedAt: time.Now().UTC(), CreatedAt: federation.Time{Time: time.Now()},
ProviderName: "GangGo", ProviderName: "GangGo",
Public: true, Public: true,
} }
...@@ -205,7 +205,7 @@ func (p ApiPost) Create() revel.Result { ...@@ -205,7 +205,7 @@ func (p ApiPost) Create() revel.Result {
} }
// save post locally // save post locally
err = post.Create(&entity, false) err = post.Create(&entity)
if err != nil { if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER) p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER) return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
...@@ -238,8 +238,8 @@ func (p ApiPost) Create() revel.Result { ...@@ -238,8 +238,8 @@ func (p ApiPost) Create() revel.Result {
dispatcher := jobs.Dispatcher{ dispatcher := jobs.Dispatcher{
User: p.CurrentUser, User: p.CurrentUser,
AspectID: aspectID,
Message: entity, Message: entity,
Model: post,
} }
go dispatcher.Run() go dispatcher.Run()
...@@ -314,6 +314,167 @@ func (p ApiPost) Show(guid string) revel.Result { ...@@ -314,6 +314,167 @@ func (p ApiPost) Show(guid string) revel.Result {
apiHelpers.SelectStructFields(post, fields)) apiHelpers.SelectStructFields(post, fields))
} }
func (p ApiPost) Delete() revel.Result { /**
return p.NotFound("Not implemented yet") * @api {delete} /posts/:guid Delete post/reshare
* @apiName ApiPost.Delete
* @apiGroup Posts
*
* @apiParam {String} access_token Oauth access token
* @apiParam {String} guid Unique global ID
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {}
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} BadRequest
* HTTP/1.1 400 BadRequest
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
*/
func (p ApiPost) Delete(guid string) revel.Result {
var post models.Post
postID, err := strconv.ParseUint(guid, 10, 32);
if err == nil {
err = post.FindByIDAndUser(uint(postID), p.CurrentUser)
} else {
err = post.FindByGuidAndUser(guid, p.CurrentUser)
}
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_POST_NOT_FOUND)
return p.ApiError(http.StatusNotFound, ERR_POST_NOT_FOUND)
}
if post.Person.ID == p.CurrentUser.Person.ID {
entity := federation.EntityRetraction{
Author: p.CurrentUser.Person.Author,
TargetGuid: post.Guid,
TargetType: models.ShareablePost,
}
dispatcher := jobs.Dispatcher{
User: p.CurrentUser,
Message: entity,
}
// NOTE relay to other hosts if we own this entity
// should be done before we start deleting db records
// thats why this call is synchron XXX we should
// change that !
dispatcher.Run()
err = post.Delete()
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return p.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
} else {
p.Log.Error(TAG, "api", ERR_BAD_REQUEST)
return p.ApiError(http.StatusBadRequest, ERR_BAD_REQUEST)
}
return p.RenderJSON(struct{}{})
}
/**
* @api {post} /posts/:guid/reshare Reshare a post
* @apiName ApiPost.Reshare
* @apiGroup Posts
*
* @apiParam {String} access_token Oauth access token
* @apiParam {String} guid Unique global ID
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {}
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} BadRequest
* HTTP/1.1 400 BadRequest
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} ServerError
* HTTP/1.1 500 Internal Server Error
* {
* "error": "[...]"
* }
*
*/
func (p ApiPost) Reshare() revel.Result {
var rootPost models.Post
var rootGuid string
p.Params.Bind(&rootGuid, "guid")
postID, err := strconv.ParseUint(rootGuid, 10, 32);
if err == nil {
err = rootPost.FindByIDAndUser(uint(postID), p.CurrentUser)
} else {
err = rootPost.FindByGuidAndUser(rootGuid, p.CurrentUser)
}
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_POST_NOT_FOUND)
return p.ApiError(http.StatusNotFound, ERR_POST_NOT_FOUND)
}
if rootPost.Person.ID == p.CurrentUser.Person.ID {
p.Log.Error(TAG, "api", ERR_BAD_REQUEST)
return p.ApiError(http.StatusBadRequest, ERR_BAD_REQUEST)
}
guid, err := helpers.Uuid()
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entity := federation.EntityReshare{
Author: p.CurrentUser.Person.Author,
Guid: guid,
CreatedAt: federation.Time{Time: time.Now()},
RootAuthor: rootPost.Person.Author,
RootGuid: rootPost.Guid,
}
var post models.Post
err = post.Create(&entity)
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
dispatcher := jobs.Dispatcher{
User: p.CurrentUser,
Model: post,
Message: entity,
}
go dispatcher.Run()
return p.RenderJSON(post)
} }
...@@ -7,19 +7,18 @@ GET /api/v0/posts ApiPost.Index ...@@ -7,19 +7,18 @@ GET /api/v0/posts ApiPost.Index
POST /api/v0/posts ApiPost.Create POST /api/v0/posts ApiPost.Create
# both guid and uint are possible here # both guid and uint are possible here
GET /api/v0/posts/:guid ApiPost.Show GET /api/v0/posts/:guid ApiPost.Show
#DELETE /api/v0/posts/:guid ApiPost.Delete DELETE /api/v0/posts/:guid ApiPost.Delete
POST /api/v0/posts/:guid/reshare ApiPost.Reshare
GET /api/v0/notifications ApiNotification.Index GET /api/v0/notifications ApiNotification.Index
#POST /api/v0/notifications ApiNotification.Create
#GET /api/v0/notifications/:id ApiNotification.Show
PUT /api/v0/notifications/:id ApiNotification.Update PUT /api/v0/notifications/:id ApiNotification.Update
DELETE /api/v0/posts/:guid/likes ApiLike.Delete
GET /api/v0/posts/:id/likes ApiLike.Index GET /api/v0/posts/:id/likes ApiLike.Index
POST /api/v0/posts/:id/likes/:positive ApiLike.Create POST /api/v0/posts/:id/likes/:positive ApiLike.Create
#GET /api/v0/posts/:id/likes/:like_id ApiLike.Show
#DELETE /api/v0/posts/:id/likes/:like_id ApiLike.Delete
GET /api/v0/comments/:id ApiComment.Show GET /api/v0/comments/:id ApiComment.Show
DELETE /api/v0/comments/:guid ApiComment.Delete
GET /api/v0/posts/:id/comments ApiComment.IndexPost GET /api/v0/posts/:id/comments ApiComment.IndexPost
POST /api/v0/posts/:id/comments ApiComment.CreatePost POST /api/v0/posts/:id/comments ApiComment.CreatePost
#GET /api/v0/posts/:id/comments/:comment_id ApiComment.Show #GET /api/v0/posts/:id/comments/:comment_id ApiComment.Show
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment