@@ -6,12 +6,14 @@ import (
66 "io/ioutil"
77 "log"
88 "net/http"
9+ "strings"
910
1011 "github.com/Sirupsen/logrus"
1112 "github.com/bstaijen/mariadb-for-microservices/comment-service/app/models"
1213 "github.com/bstaijen/mariadb-for-microservices/comment-service/config"
1314 "github.com/bstaijen/mariadb-for-microservices/comment-service/database"
1415 "github.com/bstaijen/mariadb-for-microservices/shared/util"
16+ jwt "github.com/dgrijalva/jwt-go"
1517 "github.com/urfave/negroni"
1618
1719 "strconv"
@@ -54,7 +56,7 @@ func CreateHandler(connection *sql.DB, cnf config.Config) negroni.HandlerFunc {
5456// ListCommentsHandler return a list of comments
5557func ListCommentsHandler (connection * sql.DB , cnf config.Config ) negroni.HandlerFunc {
5658 return negroni .HandlerFunc (func (w http.ResponseWriter , r * http.Request , next http.HandlerFunc ) {
57-
59+ logrus . Info ( "List comments" )
5860 offset , rows := helper .PaginationFromRequest (r )
5961
6062 // get PhotoID
@@ -98,6 +100,96 @@ func ListCommentsHandler(connection *sql.DB, cnf config.Config) negroni.HandlerF
98100 })
99101}
100102
103+ // ListCommentsFromUser : Return all comments from an user and add the photo(extra information) too.
104+ func ListCommentsFromUser (connection * sql.DB , cnf config.Config ) negroni.HandlerFunc {
105+ return negroni .HandlerFunc (func (w http.ResponseWriter , r * http.Request , next http.HandlerFunc ) {
106+ logrus .Info ("List comments from user" )
107+
108+ offset , rows := helper .PaginationFromRequest (r )
109+
110+ var queryToken = r .URL .Query ().Get ("token" )
111+
112+ if len (queryToken ) < 1 {
113+ queryToken = r .Header .Get ("token" )
114+ }
115+
116+ if len (queryToken ) < 1 {
117+ w .WriteHeader (http .StatusBadRequest )
118+ w .Write ([]byte (string ("token is mandatory" )))
119+ return
120+ }
121+
122+ tok , err := jwt .Parse (queryToken , func (t * jwt.Token ) (interface {}, error ) {
123+ return []byte (cnf .SecretKey ), nil
124+ })
125+
126+ if err != nil {
127+ util .SendErrorMessage (w , "You are not authorized" )
128+ return
129+ }
130+
131+ claims := tok .Claims .(jwt.MapClaims )
132+ var ID = claims ["sub" ].(float64 ) // gets the ID
133+
134+ comments , err := db .GetCommentsByUserID (connection , int (ID ), offset , rows )
135+
136+ // collect photo IDs.
137+ ids := make ([]* sharedModels.TopRatedPhotoResponse , 0 )
138+ f := make ([]* sharedModels.HasVotedRequest , 0 )
139+ g := make ([]* sharedModels.VoteCountRequest , 0 )
140+ for _ , v := range comments {
141+ ids = append (ids , & sharedModels.TopRatedPhotoResponse {
142+ PhotoID : v .PhotoID ,
143+ })
144+
145+ f = append (f , & sharedModels.HasVotedRequest {
146+ PhotoID : v .PhotoID ,
147+ UserID : v .UserID ,
148+ })
149+
150+ g = append (g , & sharedModels.VoteCountRequest {
151+ PhotoID : v .PhotoID ,
152+ })
153+ }
154+
155+ // get photos
156+ photos := getPhotos (cnf , ids )
157+
158+ // get votes
159+ photos = appendUserVoted (cnf , f , photos )
160+ photos = appendVotesCount (cnf , g , photos )
161+
162+ // merge with comments
163+ type Res struct {
164+ Comment * sharedModels.CommentResponse `json:"comment"`
165+ Photo * sharedModels.PhotoResponse `json:"photo"`
166+ }
167+
168+ h := make ([]* Res , 0 )
169+ for _ , v := range comments {
170+
171+ for _ , photo := range photos {
172+ if v .PhotoID == photo .ID {
173+ h = append (h , & Res {
174+ Comment : v ,
175+ Photo : photo ,
176+ })
177+ }
178+ }
179+ }
180+
181+ if err != nil {
182+ util .SendError (w , err )
183+ return
184+ }
185+
186+ type Resp struct {
187+ Result []* Res `json:"result"`
188+ }
189+ util .SendOK (w , & Resp {Result : h })
190+ })
191+ }
192+
101193// GetCommentCountHandler returns a list of counts beloning to comments.
102194func GetCommentCountHandler (connection * sql.DB , cnf config.Config ) negroni.HandlerFunc {
103195 return negroni .HandlerFunc (func (w http.ResponseWriter , r * http.Request , next http.HandlerFunc ) {
@@ -214,3 +306,168 @@ func getUsernames(cnf config.Config, input []*sharedModels.GetUsernamesRequest)
214306 })
215307 return usernames
216308}
309+
310+ func getPhotos (cnf config.Config , input []* sharedModels.TopRatedPhotoResponse ) []* sharedModels.PhotoResponse {
311+ type Req struct {
312+ Requests []* sharedModels.TopRatedPhotoResponse `json:"requests"`
313+ }
314+ body , _ := json .Marshal (& Req {Requests : input })
315+
316+ // Make url
317+ url := cnf .PhotoServiceBaseurl + "ipc/getPhotos"
318+
319+ photos := make ([]* sharedModels.PhotoResponse , 0 )
320+ if strings .HasPrefix (url , "http" ) {
321+ err := util .Request ("GET" , url , body , func (res * http.Response ) {
322+ // Error handling
323+ if res .StatusCode < 200 || res .StatusCode > 299 {
324+ printResponseError (res )
325+ return
326+ }
327+
328+ // Happy path
329+ type Collection struct {
330+ Objects []* sharedModels.PhotoResponse `json:"results"`
331+ }
332+ col := & Collection {}
333+ col .Objects = make ([]* sharedModels.PhotoResponse , 0 )
334+ err := util .ResponseJSONToObject (res , & col )
335+ if err != nil {
336+ log .Fatal (err )
337+ }
338+ photos = col .Objects
339+ })
340+ if err != nil {
341+ logrus .Fatal (err )
342+ }
343+ } else {
344+ logrus .Errorf ("Wrong URL. Expected something which starts with http, instead got %v." , url )
345+ }
346+ return photos
347+ }
348+
349+ // appendVotesCount triggers `GET votes request` and appends result to []Photo
350+ func appendVotesCount (cnf config.Config , photoCountIdentifiers []* sharedModels.VoteCountRequest , photos []* sharedModels.PhotoResponse ) []* sharedModels.PhotoResponse {
351+ // Get the vote counts and add them
352+ results := getVotes (cnf , photoCountIdentifiers )
353+ for index := 0 ; index < len (photos ); index ++ {
354+ photoObject := photos [index ]
355+
356+ for resultsIndex := 0 ; resultsIndex < len (results ); resultsIndex ++ {
357+ resultsObject := results [resultsIndex ]
358+ if photoObject .ID == resultsObject .PhotoID {
359+ photoObject .TotalVotes = resultsObject .UpVoteCount + resultsObject .DownVoteCount
360+ photoObject .UpvoteCount = resultsObject .UpVoteCount
361+ photoObject .DownvoteCount = resultsObject .DownVoteCount
362+ }
363+ }
364+ }
365+ return photos
366+ }
367+
368+ // appendUserVoted triggers `GET voted request` and appends results to []Photo. This function will
369+ // lookup whether the user has voted on the Photo
370+ func appendUserVoted (cnf config.Config , photoVotedIdentifiers []* sharedModels.HasVotedRequest , photos []* sharedModels.PhotoResponse ) []* sharedModels.PhotoResponse {
371+ youVoted := voted (cnf , photoVotedIdentifiers )
372+
373+ for index := 0 ; index < len (photos ); index ++ {
374+ photoObject := photos [index ]
375+ for votesIndex := 0 ; votesIndex < len (youVoted ); votesIndex ++ {
376+ obj := youVoted [votesIndex ]
377+
378+ if photoObject .ID == obj .PhotoID {
379+ photoObject .YouUpvote = obj .Upvote
380+ photoObject .YouDownvote = obj .Downvote
381+ }
382+ }
383+ }
384+ return photos
385+ }
386+
387+ // Get votes from the VotesSerivce
388+ func getVotes (cnf config.Config , input []* sharedModels.VoteCountRequest ) []* sharedModels.VoteCountResponse {
389+ type Req struct {
390+ Requests []* sharedModels.VoteCountRequest `json:"requests"`
391+ }
392+ body , _ := json .Marshal (& Req {Requests : input })
393+
394+ // Make url
395+ url := cnf .VoteServiceBaseurl + "ipc/count"
396+
397+ //Return object
398+ votes := make ([]* sharedModels.VoteCountResponse , 0 )
399+ if strings .HasPrefix (url , "http" ) {
400+ err := util .Request ("GET" , url , body , func (res * http.Response ) {
401+ // Error handling
402+ if res .StatusCode < 200 || res .StatusCode > 299 {
403+ printResponseError (res )
404+ return
405+ }
406+
407+ // Happy path
408+ type Collection struct {
409+ Objects []* sharedModels.VoteCountResponse `json:"results"`
410+ }
411+ col := & Collection {}
412+ col .Objects = make ([]* sharedModels.VoteCountResponse , 0 )
413+ err := util .ResponseJSONToObject (res , & col )
414+ if err != nil {
415+ logrus .Warn (err )
416+ }
417+ votes = col .Objects
418+ })
419+ if err != nil {
420+ logrus .Warn (err )
421+ }
422+ } else {
423+ logrus .Errorf ("Wrong URL. Expected something which starts with http, instead got %v." , url )
424+ }
425+ return votes
426+ }
427+
428+ // Determine if the user has voted on a photo. VotesService
429+ func voted (cnf config.Config , input []* sharedModels.HasVotedRequest ) []* sharedModels.HasVotedResponse {
430+ type Req struct {
431+ Requests []* sharedModels.HasVotedRequest `json:"requests"`
432+ }
433+ body , _ := json .Marshal (& Req {Requests : input })
434+
435+ // Make url
436+ url := cnf .VoteServiceBaseurl + "ipc/voted"
437+
438+ //Return object
439+ hasVoted := make ([]* sharedModels.HasVotedResponse , 0 )
440+ if strings .HasPrefix (url , "http" ) {
441+ err := util .Request ("GET" , url , body , func (res * http.Response ) {
442+ // Error handling
443+ if res .StatusCode < 200 || res .StatusCode > 299 {
444+ printResponseError (res )
445+ return
446+ }
447+
448+ // Happy path
449+ type Collection struct {
450+ Objects []* sharedModels.HasVotedResponse `json:"results"`
451+ }
452+ col := & Collection {}
453+ col .Objects = make ([]* sharedModels.HasVotedResponse , 0 )
454+ err := util .ResponseJSONToObject (res , & col )
455+ if err != nil {
456+ logrus .Warn (err )
457+ }
458+ hasVoted = col .Objects
459+ })
460+ if err != nil {
461+ logrus .Warn (err )
462+ }
463+ } else {
464+ logrus .Errorf ("Wrong URL. Expected something which starts with http, instead got %v." , url )
465+ }
466+ return hasVoted
467+ }
468+
469+ func printResponseError (res * http.Response ) {
470+ logrus .Errorf ("Response error with statuscode %v." , res .Status )
471+ data , _ := ioutil .ReadAll (res .Body )
472+ logrus .Error (string (data ))
473+ }
0 commit comments