Skip to content
This repository was archived by the owner on Jul 20, 2023. It is now read-only.

Commit 841f974

Browse files
committed
new layout, new overviews, full width, upload button in header
1 parent bf3965d commit 841f974

File tree

31 files changed

+1104
-61
lines changed

31 files changed

+1104
-61
lines changed

comment-service/.env.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
PORT:
22
PROFILE_SERVICE_URL:
3+
PHOTO_SERVICE_URL:
4+
VOTE_SERVICE_URL:
35
DB_USERNAME:
46
DB_PASSWORD:
57
DB_HOST:
68
DB_PORT:
7-
DB:
9+
DB:
10+
SECRET_KEY:

comment-service/app/http/controllers/controller.go

Lines changed: 258 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
5557
func 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.
102194
func 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+
}

comment-service/app/http/routes/routes.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ func setRESTRoutes(db *sql.DB, cnf config.Config, router *mux.Router) *mux.Route
2626
negroni.HandlerFunc(middleware.AcceptOPTIONS),
2727
))
2828

29+
comments.Handle("/fromuser", negroni.New(
30+
negroni.HandlerFunc(middleware.AccessControlHandler),
31+
controllers.ListCommentsFromUser(db, cnf),
32+
)).Methods("GET")
33+
2934
// Create a comment /comments
3035
comments.Methods("POST").Handler(negroni.New(
3136
negroni.HandlerFunc(middleware.AccessControlHandler),
@@ -35,6 +40,7 @@ func setRESTRoutes(db *sql.DB, cnf config.Config, router *mux.Router) *mux.Route
3540
negroni.HandlerFunc(middleware.AccessControlHandler),
3641
controllers.ListCommentsHandler(db, cnf),
3742
))
43+
3844
return router
3945
}
4046

comment-service/config/config.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import (
99
type Config struct {
1010
Port int
1111
ProfileServiceBaseurl string
12+
PhotoServiceBaseurl string
13+
VoteServiceBaseurl string
1214
DBUsername string
1315
DBPassword string
1416
DBHost string
1517
DBPort int
1618
Database string
19+
SecretKey string
1720
}
1821

1922
// LoadConfig returns the config from the environment variables
@@ -33,6 +36,14 @@ func LoadConfig() Config {
3336
config.ProfileServiceBaseurl = os.Getenv("PROFILE_SERVICE_URL")
3437
}
3538

39+
if _, ok := os.LookupEnv("PHOTO_SERVICE_URL"); ok {
40+
config.PhotoServiceBaseurl = os.Getenv("PHOTO_SERVICE_URL")
41+
}
42+
43+
if _, ok := os.LookupEnv("VOTE_SERVICE_URL"); ok {
44+
config.VoteServiceBaseurl = os.Getenv("VOTE_SERVICE_URL")
45+
}
46+
3647
if _, ok := os.LookupEnv("DB_USERNAME"); ok {
3748
config.DBUsername = os.Getenv("DB_USERNAME")
3849
}
@@ -56,6 +67,8 @@ func LoadConfig() Config {
5667
if _, ok := os.LookupEnv("DB"); ok {
5768
config.Database = os.Getenv("DB")
5869
}
59-
70+
if _, ok := os.LookupEnv("SECRET_KEY"); ok {
71+
config.SecretKey = os.Getenv("SECRET_KEY")
72+
}
6073
return config
6174
}

0 commit comments

Comments
 (0)