Skip to content

Commit

Permalink
add create-love-letter API
Browse files Browse the repository at this point in the history
  • Loading branch information
le-xuan-quynh committed May 4, 2022
1 parent 3909cc1 commit c55c12d
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 10 deletions.
14 changes: 8 additions & 6 deletions cmd/authorization/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,16 @@ const generateMatchCodeSchema = `
)
`

// schema for mail table
const mailSchema = `
create table if not exists mails (
// schema for love letter table
const loveLetterSchema = `
create table if not exists loveletter (
id Varchar(36) not null,
userid Varchar(36) not null,
matchid Varchar(36) not null default '',
matchid Varchar(36) null,
title Varchar(255) not null,
content Varchar(1000) not null,
body Varchar(32000) not null,
isread Boolean default false,
isdelete Boolean default false,
timeopen Timestamp not null,
createdat Timestamp not null,
updatedat Timestamp not null,
Expand Down Expand Up @@ -174,7 +176,7 @@ func main() {
db.MustExec(limitSchema)
db.MustExec(matchLoveSchema)
db.MustExec(generateMatchCodeSchema)
db.MustExec(mailSchema)
db.MustExec(loveLetterSchema)

logger.Info("database created")
// repository contains all the methods that interact with DB to perform CURD operations for user.
Expand Down
17 changes: 17 additions & 0 deletions internal/database/love-letter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package database

import "time"

// LoveLetter type for love letter
type LoveLetter struct {
ID string `json:"id" sql:"id"`
UserID string `json:"userid" sql:"userid"`
MatchID string `json:"matchid" sql:"matchid"`
Title string `json:"title" sql:"title"`
Body string `json:"body" sql:"body"`
IsRead bool `json:"isread" sql:"isread"`
IsDelete bool `json:"isdelete" sql:"isdelete"`
TimeOpen time.Time `json:"timeopen" sql:"timeopen"`
CreatedAt time.Time `json:"createdat" sql:"createdat"`
UpdatedAt time.Time `json:"updatedat" sql:"updatedat"`
}
22 changes: 22 additions & 0 deletions internal/database/postgres-repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,25 @@ func (repo *postgresRepository) InsertOrDeleteMatchLoveData(ctx context.Context,
return err
}
}

// CreateLoveLetter creates a love letter
func (repo *postgresRepository) CreateLoveLetter(ctx context.Context, loveLetter *LoveLetter) error {
loveLetter.ID = uuid.NewV4().String()
loveLetter.TimeOpen = time.Now()
loveLetter.CreatedAt = time.Now()
loveLetter.UpdatedAt = time.Now()
query := "insert into loveletter(id, userid, matchid, title, body, isread, isdelete, timeopen, createdat, updatedat) " +
"values($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)"
_, err := repo.db.ExecContext(ctx, query,
loveLetter.ID,
loveLetter.UserID,
loveLetter.MatchID,
loveLetter.Title,
loveLetter.Body,
loveLetter.IsRead,
loveLetter.IsDelete,
loveLetter.TimeOpen,
loveLetter.CreatedAt,
loveLetter.UpdatedAt)
return err
}
2 changes: 2 additions & 0 deletions internal/database/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ type UserRepository interface {
GetMatchLoveDataByUserID(ctx context.Context, userID string) (*MatchLoveData, error)
// InsertOrDeleteMatchLoveData Insert or update match love data
InsertOrDeleteMatchLoveData(ctx context.Context, matchData *MatchLoveData, isDelete bool) error
// CreateLoveLetter Create love letter
CreateLoveLetter(ctx context.Context, loveLetter *LoveLetter) error
}
13 changes: 11 additions & 2 deletions internal/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ const (
MatchCodeIsExpired = 23
MatchCodeIsIncorrect = 24
UserAlreadyMatched = 25
MatchCodeIsNotFound = 26
MatchCodeIsNotExactly = 26
UserNotMatch = 27
TitleRequired = 28
BodyRequired = 29
ValueTooLong = 30
)

func (e ErrorResponse) Error() string {
Expand Down Expand Up @@ -117,10 +120,16 @@ func (e ErrorResponse) Error() string {
return "match code is incorrect"
case UserAlreadyMatched:
return "user already matched"
case MatchCodeIsNotFound:
case MatchCodeIsNotExactly:
return "match code is not exactly"
case UserNotMatch:
return "user not match"
case TitleRequired:
return "title required"
case BodyRequired:
return "body required"
case ValueTooLong:
return "value too long"
default:
return "Unknown Error"
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/authorization/endpoints/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Set struct {
MatchLoverEndpoint endpoint.Endpoint
UnMatchLoverEndpoint endpoint.Endpoint
GetMatchedLoverEndpoint endpoint.Endpoint
CreateLoveLetterEndpoint endpoint.Endpoint
}

func NewEndpointSet(svc authorization.Service,
Expand Down Expand Up @@ -122,6 +123,11 @@ func NewEndpointSet(svc authorization.Service,
getMatchedLoverEndpoint = middleware.ValidateParamRequest(validator, logger)(getMatchedLoverEndpoint)
getMatchedLoverEndpoint = middleware.ValidateAccessToken(auth, logger)(getMatchedLoverEndpoint)

createLoveLetterEndpoint := MakeCreateLoveLetterEndpoint(svc)
createLoveLetterEndpoint = middleware.RateLimitRequest(tb, logger)(createLoveLetterEndpoint)
createLoveLetterEndpoint = middleware.ValidateParamRequest(validator, logger)(createLoveLetterEndpoint)
createLoveLetterEndpoint = middleware.ValidateAccessToken(auth, logger)(createLoveLetterEndpoint)

return Set{
HealthCheckEndpoint: healthCheckEndpoint,
RegisterEndpoint: registerEndpoint,
Expand All @@ -141,6 +147,7 @@ func NewEndpointSet(svc authorization.Service,
MatchLoverEndpoint: matchLoverEndpoint,
UnMatchLoverEndpoint: unMatchLoverEndpoint,
GetMatchedLoverEndpoint: getMatchedLoverEndpoint,
CreateLoveLetterEndpoint: createLoveLetterEndpoint,
}
}

Expand Down Expand Up @@ -442,3 +449,19 @@ func MakeGetMatchedLoverEndpoint(svc authorization.Service) endpoint.Endpoint {
return matchLover, nil
}
}

// MakeCreateLoveLetterEndpoint returns an endpoint that invokes CreateLoveLetter on the service.
func MakeCreateLoveLetterEndpoint(svc authorization.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req, ok := request.(authorization.CreateLoveLetterRequest)
if !ok {
cusErr := utils.NewErrorResponse(utils.BadRequest)
return nil, cusErr
}
err := svc.CreateLoveLetter(ctx, &req)
if err != nil {
return nil, err
}
return "successfully created love letter", nil
}
}
16 changes: 16 additions & 0 deletions pkg/authorization/reqresponse.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,19 @@ type UnMatchLoverRequest struct {
type GetMatchedLoverRequest struct {
AccessToken string `json:"access_token" validate:"required"`
}

// CreateLoveLetterRequest is used to create love letter
type CreateLoveLetterRequest struct {
AccessToken string `json:"access_token" validate:"required"`
Title string `json:"title" validate:"required"`
Body string `json:"body" validate:"required"`
}

//id Varchar(36) not null,
//userid Varchar(36) not null,
//matchid Varchar(36) null,
//title Varchar(255) not null,
//content Varchar(1000) not null,
//timeopen Timestamp not null,
//createdat Timestamp not null,
//updatedat Timestamp not null,
1 change: 1 addition & 0 deletions pkg/authorization/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ type Service interface {
MatchLover(ctx context.Context, request *MatchLoverRequest) error
UnMatchedLover(ctx context.Context) error
GetMatchLover(ctx context.Context) (interface{}, error)
CreateLoveLetter(ctx context.Context, request *CreateLoveLetterRequest) error
}
30 changes: 30 additions & 0 deletions pkg/authorization/transport/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ func NewHTTPHandler(ep endpoints.Set) http.Handler {
encodeResponse,
options...,
))
m.Handle("/create-love-letter", httptransport.NewServer(
ep.CreateLoveLetterEndpoint,
decodeHTTPCreateLoveLetterRequest,
encodeResponse,
options...,
))

mux := http.NewServeMux()
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", m))
Expand Down Expand Up @@ -474,6 +480,30 @@ func decodeHTTPGetMatchedLoverRequest(_ context.Context, r *http.Request) (inter
}
}

// decodeHTTPCreateLoveLetterRequest decode request
func decodeHTTPCreateLoveLetterRequest(_ context.Context, r *http.Request) (interface{}, error) {
if r.Method == "POST" {
var req authorization.CreateLoveLetterRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return nil, utils.NewErrorResponse(utils.BadRequest)
}
if req.AccessToken == "" {
return nil, utils.NewErrorResponse(utils.AccessTokenRequired)
}
if req.Title == "" {
return nil, utils.NewErrorResponse(utils.TitleRequired)
}
if req.Body == "" {
return nil, utils.NewErrorResponse(utils.BodyRequired)
}
return req, nil
} else {
cusErr := utils.NewErrorResponse(utils.MethodNotAllowed)
return nil, cusErr
}
}

// encodeResponse encode response
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
Expand Down
52 changes: 50 additions & 2 deletions pkg/authorization/users-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ func (s *userService) MatchLover(ctx context.Context, request *MatchLoverRequest
matchData, err := s.repo.GetMatchVerifyDataByCode(ctx, request.Code)
if err != nil {
s.logger.Error("Cannot get match data", "error", err)
cusErr := utils.NewErrorResponse(utils.MatchCodeIsNotFound)
cusErr := utils.NewErrorResponse(utils.MatchCodeIsNotExactly)
return cusErr
}
if matchData.Code == "" {
Expand Down Expand Up @@ -1073,7 +1073,7 @@ func (s *userService) UnMatchedLover(ctx context.Context) error {
cusErr := utils.NewErrorResponse(utils.InternalServerError)
return cusErr
}
s.logger.Debug("Successfully unmatch lover")
s.logger.Debug("Successfully unmatched lover")
return nil
}

Expand Down Expand Up @@ -1131,3 +1131,51 @@ func (s *userService) GetMatchLover(ctx context.Context) (interface{}, error) {
}
return response, nil
}

// CreateLoveLetter create love letter
func (s *userService) CreateLoveLetter(ctx context.Context, request *CreateLoveLetterRequest) error {
userID, ok := ctx.Value(middleware.UserIDKey{}).(string)
if !ok {
s.logger.Error("Error getting userID from context")
cusErr := utils.NewErrorResponse(utils.InternalServerError)
return cusErr
}
user, err := s.repo.GetUserByID(ctx, userID)
if err != nil {
s.logger.Error("Cannot get user", "error", err)
cusErr := utils.NewErrorResponse(utils.InternalServerError)
return cusErr
}
// Check if user is banned
if user.Banned {
s.logger.Error("User is banned", "error", err)
cusErr := utils.NewErrorResponse(utils.Forbidden)
return cusErr
}
// Get match lover
matchID := ""
matchLove, err := s.repo.GetMatchLoveDataByUserID(ctx, user.ID)
if err != nil {
s.logger.Error("User does not match with someone", "error", err)
}
matchID = matchLove.MatchID
// Create love letter
loveLetter := &database.LoveLetter{
UserID: user.ID,
MatchID: matchID,
Title: request.Title,
Body: request.Body,
}
err = s.repo.CreateLoveLetter(ctx, loveLetter)
if err != nil {
s.logger.Error("Cannot create love letter", "error", err)
if strings.Contains(err.Error(), "value too long for type character varying") {
cusErr := utils.NewErrorResponse(utils.ValueTooLong)
return cusErr
}
cusErr := utils.NewErrorResponse(utils.InternalServerError)
return cusErr
}
s.logger.Debug("Successfully create love letter")
return nil
}

0 comments on commit c55c12d

Please sign in to comment.