Skip to content

Commit

Permalink
Merge pull request #27 from Dhruv9449/v2
Browse files Browse the repository at this point in the history
Auth middleware, updated parsing and few other improvements
  • Loading branch information
Dhruv9449 authored Dec 24, 2023
2 parents e47ac0d + c85f041 commit 888e441
Show file tree
Hide file tree
Showing 27 changed files with 857 additions and 217 deletions.
2 changes: 1 addition & 1 deletion traefik/traefik.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ certificatesResolvers:
http:
routers:
web-secure-router:
rule: "Host(`vitty-backend.dhruvshah.live`)"
rule: "Host(`vitty-api.dhruvshah.live`)"
entryPoints:
- web-secure
service: vitty-api
Expand Down
215 changes: 215 additions & 0 deletions vitty-backend-api/admin/pkg/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package pkg

import (
"fmt"
"html/template"
"io"
"net/http"
"reflect"

"github.com/labstack/echo/v4"
)

type TemplateRenderer struct {
templates *template.Template
}

func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
if viewContext, isMap := data.(map[string]interface{}); isMap {
viewContext["reverse"] = c.Echo().Reverse
}

return t.templates.ExecuteTemplate(w, name, data)
}

func AdminHandler(app *echo.Echo) {
group := app.Group("")
group.Use(JWTMiddleware)
group.GET("", GetModelsView)
group.GET("/:model", GetModelView)
group.GET("/:model/create", CreateItemView)
group.POST("/:model/create", CreateItem)
group.GET("/:model/:id", GetItemView)
group.GET("/:model/:id/edit", UpdateItemView)
group.PUT("/:model/:id", UpdateItem)
group.DELETE("/:model/:id", DeleteItem)
}

func GetModelsView(c echo.Context) error {
fmt.Println("list models")
svc := c.Get("svc").(*AdminSvc)
models := svc.GetModels()
// Model names -
var names []string
for _, model := range models {
names = append(names, GetModelName(model))
}
return c.Render(http.StatusOK, "list-models.html", map[string]interface{}{
"model_names": names,
})
}

func GetModelView(c echo.Context) error {
fmt.Println("get model")
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
fmt.Println("Model", model)
if model == nil {
fmt.Println("Model not found")
return c.Redirect(http.StatusFound, "/")
}
items, err := model.GetAll()
fmt.Println("Items", items)
var itemList []map[string]interface{}
for _, item := range items {
itemList = append(itemList, map[string]interface{}{
"pk_field": model.GetPKField(),
"pk_value": GetPKValue(item, model.GetPKField()),
"item_name": item.GetItemName(),
})
}
fmt.Println("item list", itemList)
if err != nil {
fmt.Println("Error", err)
return c.Redirect(http.StatusFound, "/")
}
return c.Render(http.StatusOK, "list-items.html", map[string]interface{}{
"model": modelName,
"fields": GetFields(model),
"items": itemList,
})
}

func CreateItemView(c echo.Context) error {
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
if model == nil {
return c.Redirect(http.StatusFound, "/")
}
return c.Render(http.StatusOK, "create-model.html", map[string]interface{}{
"model": GetModelName(model),
"fields": GetFields(model),
})
}

func CreateItem(c echo.Context) error {
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
if model == nil {
return c.Redirect(http.StatusFound, "/")
}
model.Create(model)
return c.Redirect(http.StatusFound, "/"+modelName)
}

func GetItemView(c echo.Context) error {
fmt.Println("get item")
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
if model == nil {
fmt.Println("Model not found")
return c.Redirect(http.StatusFound, "/")
}
id := c.Param("id")
item, err := model.Get(id)
if err != nil {
fmt.Println("Error", err)
return c.Redirect(http.StatusFound, "/"+modelName)
}
fmt.Println("Item", item)

itemMap := make(map[string]string)
for fieldName := range GetFields(model) {
itemMap[fieldName] = fmt.Sprintf("%v", reflect.ValueOf(item).Elem().FieldByName(fieldName))
}
fmt.Println("Item Map", itemMap)

return c.Render(http.StatusOK, "get-item.html", map[string]interface{}{
"model": GetModelName(model),
"fields": GetFields(model),
"item_name": item.GetItemName(),
"pk_value": GetPKValue(item, model.GetPKField()),
"item": &item,
"item_map": itemMap,
})
}

func UpdateItemView(c echo.Context) error {
fmt.Println("update item")
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
if model == nil {
fmt.Println("Model not found")
return c.Redirect(http.StatusFound, "/")
}
id := c.Param("id")
item, err := model.Get(id)
if err != nil {
fmt.Println("Error", err)
return c.Redirect(http.StatusFound, "/"+modelName)
}
fmt.Println("Item", item)

itemMap := make(map[string]string)
for fieldName := range GetFields(model) {
itemMap[fieldName] = fmt.Sprintf("%v", reflect.ValueOf(item).Elem().FieldByName(fieldName))
}
fmt.Println("Item Map", itemMap)

return c.Render(http.StatusOK, "update-item.html", map[string]interface{}{
"model": GetModelName(model),
"fields": GetFields(model),
"item_name": item.GetItemName(),
"pk_value": GetPKValue(item, model.GetPKField()),
"item": &item,
"item_map": itemMap,
})
}

func UpdateItem(c echo.Context) error {
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
if model == nil {
return c.Redirect(http.StatusFound, "/")
}
id := c.Param("id")
item, err := model.Get(id)
if err != nil {
c.Logger().Error(err)
return c.Redirect(http.StatusFound, "/"+modelName)
}
err = model.Update(item)
if err != nil {
c.Logger().Error(err)
return c.Redirect(http.StatusFound, "/"+modelName)
}
return c.Redirect(http.StatusFound, "/"+modelName+"/"+id)
}

func DeleteItem(c echo.Context) error {
svc := c.Get("svc").(*AdminSvc)
modelName := c.Param("model")
model := svc.GetModel(modelName)
if model == nil {
return c.JSON(http.StatusNotFound, map[string]interface{}{
"message": "Model not found",
})
}
id := c.Param("id")
item, err := model.Get(id)
if err != nil {
return c.JSON(http.StatusNotFound, map[string]interface{}{
"message": "Item not found",
})
}
model.Delete(item)
return c.JSON(http.StatusOK, map[string]interface{}{
"message": "Item deleted",
})
}
16 changes: 16 additions & 0 deletions vitty-backend-api/admin/pkg/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package pkg

import "github.com/labstack/echo/v4"

func JWTMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
return next(c)
}
}

func (svc *AdminSvc) AddSVCToEchoContext(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Set("svc", svc)
return next(c)
}
}
21 changes: 21 additions & 0 deletions vitty-backend-api/admin/pkg/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pkg

// type ModelInterface interface {
// GetAll() ([]ModelInterface, error)
// Get(id string) (ModelInterface, error)
// GetPKField() string
// GetItemName() string
// Create(model interface{}) error
// Update(model interface{}) error
// Delete(model interface{}) error
// }

type ModelInterface interface {
GetAll() ([]ModelInterface, error)
Get(id string) (ModelInterface, error)
GetPKField() string
GetItemName() string
Create(model ModelInterface) error
Update(model ModelInterface) error
Delete(model ModelInterface) error
}
100 changes: 100 additions & 0 deletions vitty-backend-api/admin/pkg/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package pkg

import (
"fmt"
"html/template"
"path/filepath"
"reflect"
"runtime"

"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)

type AdminSvc struct {
Models []ModelInterface
WebApp *echo.Echo
}

func NewAdminSvc() *AdminSvc {
svc := &AdminSvc{}
svc.init()
return svc
}

func (s *AdminSvc) init() {
s.WebApp = echo.New()
// Logger
s.WebApp.Use(middleware.Logger())
s.WebApp.Use(s.AddSVCToEchoContext)

_, currentFile, _, _ := runtime.Caller(0) // Get the path of the current file
currentDir := filepath.Dir(currentFile)
templatesPath := filepath.Join(currentDir, "../templates")

renderer := &TemplateRenderer{
templates: template.Must(template.ParseGlob(templatesPath + "/*.html")),
}
s.WebApp.Renderer = renderer
s.WebApp.GET("", func(c echo.Context) error {
fmt.Println("Hello World")
return c.JSON(200, map[string]interface{}{
"message": "Hello World",
})
})
AdminHandler(s.WebApp)
}

func (s *AdminSvc) Register(model ModelInterface) {
s.Models = append(s.Models, model)
}

func (s *AdminSvc) GetModels() []ModelInterface {
return s.Models
}

func (s *AdminSvc) GetModel(modelName string) ModelInterface {
for _, model := range s.Models {
if reflect.TypeOf(model).Elem().Name() == modelName {
return model
}
}
return nil
}

func GetModelName(model ModelInterface) string {
return reflect.TypeOf(model).Elem().Name()
}

func GetFields(model ModelInterface) map[string]string {
fields := make(map[string]string)
modelType := reflect.TypeOf(model)
if modelType.Kind() == reflect.Ptr {
modelType = modelType.Elem()
}

if modelType.Kind() == reflect.Struct {
for i := 0; i < modelType.NumField(); i++ {
field := modelType.Field(i)
fields[field.Name] = field.Type.Name()
}
}

return fields
}

func GetPKValue(item interface{}, pkField string) interface{} {
itemValue := reflect.ValueOf(item)
if itemValue.Kind() == reflect.Ptr {
itemValue = itemValue.Elem()
}

fieldValue := itemValue.FieldByName(pkField)
if !fieldValue.IsValid() {
// Handle the case where the field does not exist
fmt.Println("Field does not exist")
return nil
}

return fieldValue.Interface()
}
Empty file.
Empty file.
Loading

0 comments on commit 888e441

Please sign in to comment.