Skip to content

Commit

Permalink
change migration seq to start from 000001 for go lang migrate & add `…
Browse files Browse the repository at this point in the history
…shareable_id` column (#52)

* change seq to start from 1 for go lang migrate

* create migration to add shareable id column in form table

* add comments to create, version & force commands in makerfile

* drop index in shareable id down migration

* remove spacing

* add the wisee prefix to pathname in google redirect url

* fix build error

* add a todo

* chore: Generate shareable ID for new forms (#53)

* create an api to get form details from shareable_id (#54)

* chore: Generate shareable ID for new forms

* create a api to get form details from shareable id

* share shareable id to GetFormDetailsResposneDto & write test cases to get form details form shareable id api
  • Loading branch information
yesyash authored May 20, 2024
1 parent dc3aaf5 commit 9c44501
Show file tree
Hide file tree
Showing 16 changed files with 194 additions and 10 deletions.
32 changes: 32 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,38 @@ migrate-all-down:
exit 1; \
fi

# Create a new migration file
# ---
# Example: make migrate-create name=create_users_table
migrate-create:
@if command -v migrate > /dev/null; then \
migrate create -ext sql -dir database/migrations -seq $(name); \
else \
echo "Golang Migrate cli is not installed on your machine. Exiting..."; \
exit 1; \
fi

# Get the current migration version
# ---
migrate-version:
@if command -v migrate > /dev/null; then \
migrate -database $(DEV_DATABASE_URL) -path ./database/migrations version; \
else \
echo "Golang Migrate cli is not installed on your machine. Exiting..."; \
exit 1; \
fi

# Set the verion of the migration, without running it
# ---
# Example: make migrate-set-version version=1
migrate-force:
@if command -v migrate > /dev/null; then \
migrate -database $(DEV_DATABASE_URL) -path ./database/migrations force $(version); \
else \
echo "Golang Migrate cli is not installed on your machine. Exiting..."; \
exit 1; \
fi

# Setup Databse and PGAdmin
docker-run:
@if command -v docker > /dev/null; then \
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions database/migrations/000003_shareable_id.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BEGIN;

DROP INDEX IF EXISTS shareable_id_idx;
ALTER TABLE forms.form DROP COLUMN shareable_id;

COMMIT;
6 changes: 6 additions & 0 deletions database/migrations/000003_shareable_id.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BEGIN;

ALTER TABLE forms.form ADD COLUMN shareable_id VARCHAR(255) UNIQUE NOT NULL;
CREATE UNIQUE INDEX shareable_id_idx ON forms.form (shareable_id);

COMMIT;
2 changes: 0 additions & 2 deletions database/migrations/20230912210234_users.down.sql

This file was deleted.

6 changes: 0 additions & 6 deletions database/migrations/20230912210234_users.up.sql

This file was deleted.

2 changes: 1 addition & 1 deletion environments/dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ DB_MAX_OPEN_CONNECTIONS=10

GOOGLE_CLIENT_ID="google-client-id"
GOOGLE_CLIENT_SECRET="google-client-secret"
GOOGLE_REDIRECT_URL="http://localhost:8080/v1/auth/google/callback"
GOOGLE_REDIRECT_URL="http://localhost:8080/wisee/v1/auth/google/callback"
2 changes: 1 addition & 1 deletion environments/test.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ DB_MAX_OPEN_CONNECTIONS=10

GOOGLE_CLIENT_ID="google-client-id"
GOOGLE_CLIENT_SECRET="google-client-secret"
GOOGLE_REDIRECT_URL="http://localhost:8080/v1/auth/google/callback"
GOOGLE_REDIRECT_URL="http://localhost:8080/wisee/v1/auth/google/callback"
2 changes: 2 additions & 0 deletions src/dtos/http_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type CreateUpdateGetFormResponseDto struct {
CreatedById int64 `json:"created_by_id"`
Status string `json:"status"`
UpdatedById *int64 `json:"updated_by_id"`
ShareableId string `json:"shareable_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
Expand All @@ -48,6 +49,7 @@ type GetFormsResponseDto []CreateUpdateGetFormResponseDto
type GetFormDetailResponseDto struct {
Id int64 `json:"id"`
OwnerId int64 `json:"owner_id"`
ShareableId string `json:"shareable_id"`
Status string `json:"status"`
CreatedById int64 `json:"created_by_id"`
UpdatedById *int64 `json:"updated_by_id"`
Expand Down
1 change: 1 addition & 0 deletions src/models/forms.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Form struct {
bun.BaseModel `bun:"table:forms.form"`

Id int64 `bun:"id,pk,autoincrement" json:"id"`
ShareableId string `bun:"shareable_id" json:"shareable_id"`
Content FormContent `bun:"content" json:"content"`
CreatedById int64 `bun:"created_by_id" json:"created_by_id"`
CreatedBy *User `bun:"rel:belongs-to,join:created_by_id=id" json:"created_by"`
Expand Down
100 changes: 100 additions & 0 deletions src/routes/forms.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package routes

import (
"encoding/json"
"net/http"
"strconv"

"github.com/Real-Dev-Squad/wisee-backend/src/dtos"
"github.com/Real-Dev-Squad/wisee-backend/src/models"
"github.com/Real-Dev-Squad/wisee-backend/src/utils"
"github.com/gin-gonic/gin"
"github.com/uptrace/bun"
)
Expand All @@ -26,13 +29,52 @@ func FormRoutes(rg *gin.RouterGroup, db *bun.DB) {
return
}

/**
* Stringify the content to generate a hash
* ---
*/
stringifiedJson, marshalErr := json.Marshal(requestBody.Content)

if marshalErr != nil {
errObj := dtos.ResponseDto{
Message: "invalid request",
Error: &dtos.ErrorResponse{
Message: "invalid request body",
Detail: "error reading the content",
},
}

ctx.JSON(http.StatusBadRequest, errObj)
return
}

// create a key from the content and the id of the user who created the form
shareableIdKey := string(stringifiedJson) + strconv.FormatInt(requestBody.PerformedById, 10)
shareableId, hashErr := utils.GenerateHash(shareableIdKey, 5)

if hashErr != nil {
errObj := dtos.ResponseDto{
Message: "invalid request",
Error: &dtos.ErrorResponse{
Message: "invalid request body",
Detail: "error generating shareable id",
},
}

ctx.JSON(http.StatusBadRequest, errObj)
return
}

var form = &models.Form{
Content: requestBody.Content,
CreatedById: requestBody.PerformedById,
Status: models.DRAFT,
OwnerId: requestBody.PerformedById,
ShareableId: shareableId,
}

// Create a new form
// ---
if _, err := db.NewInsert().Model(form).Exec(ctx); err != nil {
errObj := dtos.ResponseDto{
Message: "something went wrong",
Expand All @@ -49,6 +91,8 @@ func FormRoutes(rg *gin.RouterGroup, db *bun.DB) {
FormId: form.Id,
}

// Create a new entry using the form created above
// ---
if _, err := db.NewInsert().Model(FormMetaData).Exec(ctx); err != nil {
errObj := dtos.ResponseDto{
Message: "something went wrong",
Expand All @@ -67,6 +111,7 @@ func FormRoutes(rg *gin.RouterGroup, db *bun.DB) {
OwnerId: form.OwnerId,
CreatedById: form.CreatedById,
Status: string(form.Status),
ShareableId: form.ShareableId,
CreatedAt: form.CreatedAt.String(),
UpdatedAt: form.UpdatedAt.String(),
}
Expand Down Expand Up @@ -143,6 +188,61 @@ func FormRoutes(rg *gin.RouterGroup, db *bun.DB) {
CreatedAt: form.CreatedAt.String(),
UpdatedAt: form.UpdatedAt.String(),
Content: form.Content,
ShareableId: form.ShareableId,
Meta: dtos.GetFormMetaDataResponseDto{
Id: formMetaData.Id,
FormId: formMetaData.FormId,
IsDeleted: formMetaData.IsDeleted,
AccepctingResponses: formMetaData.AccepctingResponses,
AllowGuestResponses: formMetaData.AllowGuestResponses,
AllowMultipleRepsonses: formMetaData.AllowMultipleRepsonses,
SendConfirmationEmailToRespondee: formMetaData.SendConfirmationEmailToRespondee,
SendSubmissionEmailToOwner: formMetaData.SendSubmissionEmailToOwner,
ValidTill: formMetaData.ValidTill,
UpdatedById: formMetaData.UpdatedById,
UpdatedAt: formMetaData.UpdatedAt,
},
}

var res = dtos.ResponseDto{
Message: "form fetched successfully",
Data: resData,
}

ctx.JSON(http.StatusOK, res)
})

forms.GET("/share/:shareableId", func(ctx *gin.Context) {
var formMetaData models.FormMetaData
var form models.Form
shareable_id := ctx.Param("shareableId")

query := db.NewSelect().Model(&formMetaData).Relation("Form").Where("shareable_id = ?", shareable_id)
if err := query.Scan(ctx); err != nil {
errObj := dtos.ResponseDto{
Message: "something went wrong",
Error: &dtos.ErrorResponse{
Message: "error fetching form",
Detail: err.Error(),
},
}
ctx.JSON(http.StatusBadRequest, errObj)
return
}

form = *formMetaData.Form

// TODO - @yesyash : trim down the response size (createdAt, updatedAt), we don't need all the fields
var resData = dtos.GetFormDetailResponseDto{
Id: form.Id,
OwnerId: form.OwnerId,
Status: string(form.Status),
CreatedById: form.CreatedById,
UpdatedById: form.UpdatedById,
CreatedAt: form.CreatedAt.String(),
UpdatedAt: form.UpdatedAt.String(),
Content: form.Content,
ShareableId: form.ShareableId,
Meta: dtos.GetFormMetaDataResponseDto{
Id: formMetaData.Id,
FormId: formMetaData.FormId,
Expand Down
17 changes: 17 additions & 0 deletions src/utils/generate-hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package utils

import (
"crypto/md5"
"encoding/hex"
)

func GenerateHash(content string, length int8) (string, error) {
hash := md5.New()
_, err := hash.Write([]byte(content))

if err != nil {
return "", err
}

return hex.EncodeToString(hash.Sum(nil))[:length], nil
}
28 changes: 28 additions & 0 deletions tests/integration/form_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,31 @@ func TestFormUpdateInavlidFormId(t *testing.T) {
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, respBody.Error.Detail, "no rows in result set")
}

func TestFormGetByShareableId(t *testing.T) {
router := routes.SetupV1Routes(db)
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", fmt.Sprintf("/wisee/v1/forms/share/%v", form.ShareableId), nil)

router.ServeHTTP(w, req)
if err != nil {
t.Fatal(err)
}

var respBody TestResponseDto
if err := json.NewDecoder(w.Body).Decode(&respBody); err != nil {
t.Fatal(err)
}

var resData dtos.GetFormDetailResponseDto
if err := json.Unmarshal(respBody.Data, &resData); err != nil {
t.Fatal(err)
}

assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "form fetched successfully", respBody.Message)
assert.Equal(t, form.Id, resData.Id)
assert.Equal(t, form.OwnerId, resData.OwnerId)
assert.Equal(t, string(form.Status), resData.Status)
assert.Equal(t, form.ShareableId, resData.ShareableId)
}

0 comments on commit 9c44501

Please sign in to comment.