API package refactor
This commit is contained in:
parent
a7cd86962e
commit
bc6b57bc54
14 changed files with 474 additions and 416 deletions
27
apis/base.go
Normal file
27
apis/base.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var db *gorm.DB
|
||||
|
||||
func BindAPIs(r *gin.Engine, cfg_db *gorm.DB) error {
|
||||
if cfg_db == nil {
|
||||
return errors.New("Database is null")
|
||||
}
|
||||
db = cfg_db
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "pong",
|
||||
})
|
||||
})
|
||||
bindPlanAPIs(r)
|
||||
bindPollAPIs(r)
|
||||
bindUserAPIs(r)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
package main
|
||||
package apis
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"planner/models"
|
||||
"planner/core"
|
||||
)
|
||||
|
||||
func ExtractUser(orm *gorm.DB, c *gin.Context) *models.User {
|
||||
func extractUser(orm *gorm.DB, c *gin.Context) *core.User {
|
||||
username, _, ok := c.Request.BasicAuth()
|
||||
if !ok {
|
||||
c.Status(http.StatusUnauthorized)
|
||||
return nil
|
||||
}
|
||||
u := models.User{
|
||||
u := core.User{
|
||||
Username: username,
|
||||
}
|
||||
|
||||
262
apis/plans.go
Normal file
262
apis/plans.go
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
. "planner/core"
|
||||
)
|
||||
|
||||
func createPlan(c *gin.Context) {
|
||||
u := extractUser(db, c)
|
||||
if u == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var plan_req struct {
|
||||
Name string `json:"name" form:"name"`
|
||||
}
|
||||
c.Bind(&plan_req)
|
||||
var plan Plan = Plan{
|
||||
Name: plan_req.Name,
|
||||
Owner: u.Username,
|
||||
Members: []Member{
|
||||
{
|
||||
UserID: u.Username,
|
||||
Type: "user",
|
||||
Status: "ready",
|
||||
JoinCode: "owner",
|
||||
},
|
||||
},
|
||||
}
|
||||
result := db.Create(&plan)
|
||||
|
||||
if result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, result.Error)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, plan_req)
|
||||
}
|
||||
}
|
||||
|
||||
func listPlans(c *gin.Context) {
|
||||
u := extractUser(db, c)
|
||||
if u == nil {
|
||||
return
|
||||
}
|
||||
plans, err := u.GetPlans(db)
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, plans)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func getPlan(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
Id uint `uri:"id"`
|
||||
}
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(db, *user, params.Id)
|
||||
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, plan)
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
} else if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func listPlanMembers(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan_id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(db, *user, uint(plan_id))
|
||||
members, err := plan.GetAllUsers(db)
|
||||
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, members)
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
} else if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func addPlanMember(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan_id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(db, *user, uint(plan_id))
|
||||
|
||||
var new_member Member
|
||||
if err := c.ShouldBind(&new_member); err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = plan.AddMember(db, &new_member)
|
||||
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, new_member)
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
} else if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func joinPlan(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan_id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
plan, err := GetPlan(db, *user, uint(plan_id))
|
||||
if err != nil {
|
||||
c.Status(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
member, err := plan.GetMember(db, user)
|
||||
var query struct {
|
||||
JoinCode string `fdb:"code"`
|
||||
}
|
||||
if c.ShouldBindQuery(&query) != nil || query.JoinCode == "" {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if member.Status != "pending" {
|
||||
c.String(http.StatusConflict, "User is not pending")
|
||||
return
|
||||
}
|
||||
if member.JoinCode == query.JoinCode {
|
||||
member.Status = "ready"
|
||||
err := db.Model(&member).Update("status", member.Status).Error
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.String(http.StatusConflict, "Invalid join code")
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
func createPlanPoll(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
Id uint `uri:"id"`
|
||||
}
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(db, *user, params.Id)
|
||||
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
} else if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var poll_opts struct {
|
||||
Options string `json:"options"`
|
||||
}
|
||||
bind_result = c.Bind(&poll_opts)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
|
||||
poll := Poll{
|
||||
PlanID: plan.ID,
|
||||
Options: poll_opts.Options,
|
||||
}
|
||||
db.Create(&poll)
|
||||
|
||||
c.JSON(http.StatusCreated, poll)
|
||||
}
|
||||
|
||||
func listPlanPolls(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
Id uint `uri:"id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var polls []Poll
|
||||
db.Where("plan_id = ?", params.Id).Find(&polls)
|
||||
c.JSON(http.StatusOK, polls)
|
||||
}
|
||||
|
||||
func bindPlanAPIs(r *gin.Engine) {
|
||||
r.POST("/plans", createPlan)
|
||||
r.GET("/plans", listPlans)
|
||||
r.GET("/plans/:id", getPlan)
|
||||
r.GET("/plans/:id/members", listPlanMembers)
|
||||
r.POST("/plans/:id/members", addPlanMember)
|
||||
r.GET("/plans/:id/join", joinPlan)
|
||||
r.POST("/plans/:id/polls", createPlanPoll)
|
||||
r.GET("/plans/:id/polls", listPlanPolls)
|
||||
}
|
||||
91
apis/polls.go
Normal file
91
apis/polls.go
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"planner/core"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func getPoll(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
PollId uint `uri:"poll_id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
fmt.Println(params)
|
||||
|
||||
poll, _ := core.GetPoll(db, *user, params.PollId)
|
||||
c.JSON(http.StatusOK, poll)
|
||||
}
|
||||
|
||||
func getPollVotes(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
PollId uint `uri:"poll_id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
|
||||
var votes []core.Vote
|
||||
db.Where("poll_id = ?", params.PollId).Find(&votes)
|
||||
c.JSON(http.StatusOK, &votes)
|
||||
}
|
||||
|
||||
func pollVote(c *gin.Context) {
|
||||
user := extractUser(db, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var path_params struct {
|
||||
PollId uint `uri:"poll_id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(&path_params)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
|
||||
poll, err := core.GetPoll(db, *user, path_params.PollId)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var vote_params struct {
|
||||
Vote string `json:"vote"`
|
||||
}
|
||||
c.Bind(&vote_params)
|
||||
|
||||
if err := poll.SetVote(db, *user, vote_params.Vote); err != nil {
|
||||
c.String(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
func bindPollAPIs(r *gin.Engine) {
|
||||
r.GET("/polls/:poll_id", getPoll)
|
||||
r.GET("/polls/:poll_id/votes", getPollVotes)
|
||||
r.POST("/polls/:poll_id/votes", pollVote)
|
||||
}
|
||||
64
apis/users.go
Normal file
64
apis/users.go
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
. "planner/core"
|
||||
)
|
||||
|
||||
func getUserByName(c *gin.Context) {
|
||||
var q struct {
|
||||
Name string `fdb:"name"`
|
||||
}
|
||||
if c.ShouldBind(&q) == nil {
|
||||
user := User{
|
||||
Username: q.Name,
|
||||
}
|
||||
db.Take(&user)
|
||||
fmt.Println(user)
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
||||
}
|
||||
|
||||
func createUser(c *gin.Context) {
|
||||
var u User
|
||||
if c.ShouldBind(&u) == nil {
|
||||
db.Create(&u)
|
||||
c.Status(http.StatusCreated)
|
||||
} else {
|
||||
fmt.Print("Could not bind model")
|
||||
c.String(http.StatusInternalServerError, "Unable to bind user")
|
||||
}
|
||||
}
|
||||
|
||||
func login(c *gin.Context) {
|
||||
var q struct {
|
||||
Username string `json:"username" form:"username"`
|
||||
Password string `json:"password" form:"password"`
|
||||
}
|
||||
if c.ShouldBind(&q) == nil {
|
||||
if q.Username == "" {
|
||||
c.String(http.StatusBadRequest, "Login data is null")
|
||||
} else {
|
||||
user := User{
|
||||
Username: q.Username,
|
||||
}
|
||||
db.Take(&user)
|
||||
if user.Password == q.Password {
|
||||
c.JSON(http.StatusOK, map[string]string{"username": user.Username})
|
||||
} else {
|
||||
c.Status(http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.String(http.StatusBadRequest, "Unable to bind data")
|
||||
}
|
||||
}
|
||||
func bindUserAPIs(r *gin.Engine) {
|
||||
r.POST("/login", login)
|
||||
r.GET("/user", getUserByName)
|
||||
r.POST("/user", createUser)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package errors
|
||||
package core
|
||||
|
||||
import "errors"
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package core
|
||||
|
||||
type User struct {
|
||||
Username string `gorm:"primaryKey" json:"username"`
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
package models
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
. "planner/errors"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
package models
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"planner/errors"
|
||||
)
|
||||
|
||||
func GetPoll(orm *gorm.DB, user User, id uint) (*Poll, error) {
|
||||
|
|
@ -33,7 +32,7 @@ func (p *Poll) SetVote(orm *gorm.DB, user User, option string) error {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
return errors.ErrInvalidOption
|
||||
return ErrInvalidOption
|
||||
}
|
||||
|
||||
if res := orm.Create(Vote{PollID: p.ID, UsernameID: user.Username, Value: option}); res.Error != nil {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package models
|
||||
package core
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
2
db.go
2
db.go
|
|
@ -5,7 +5,7 @@ import (
|
|||
"gorm.io/gorm"
|
||||
"log"
|
||||
"os"
|
||||
. "planner/models"
|
||||
. "planner/core"
|
||||
)
|
||||
|
||||
func bootstrapDatabase() *gorm.DB {
|
||||
|
|
|
|||
11
go.mod
11
go.mod
|
|
@ -2,6 +2,13 @@ module planner
|
|||
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/mattn/go-sqlite3 v1.14.23
|
||||
gorm.io/driver/sqlite v1.5.6
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.12.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||
|
|
@ -9,7 +16,6 @@ require (
|
|||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.10.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||
|
|
@ -20,7 +26,6 @@ require (
|
|||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.23 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
|
|
@ -33,6 +38,4 @@ require (
|
|||
golang.org/x/text v0.18.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/sqlite v1.5.6 // indirect
|
||||
gorm.io/gorm v1.25.12 // indirect
|
||||
)
|
||||
|
|
|
|||
11
go.sum
11
go.sum
|
|
@ -8,6 +8,7 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ
|
|||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
|
|
@ -15,6 +16,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
|||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
|
|
@ -23,6 +26,8 @@ github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4
|
|||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
|
|
@ -47,6 +52,7 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
|
|
@ -56,6 +62,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
|
|
@ -73,8 +80,11 @@ golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
|||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
@ -84,4 +94,3 @@ gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDa
|
|||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
|
|||
400
planner.go
400
planner.go
|
|
@ -1,15 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
. "planner/errors"
|
||||
"planner/models"
|
||||
. "planner/models"
|
||||
"planner/apis"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
|
|
@ -29,396 +23,6 @@ func main() {
|
|||
defer db.Close()
|
||||
|
||||
r := gin.Default()
|
||||
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "pong",
|
||||
})
|
||||
})
|
||||
|
||||
r.POST("/login", func(c *gin.Context) {
|
||||
var q struct {
|
||||
Username string `json:"username" form:"username"`
|
||||
Password string `json:"password" form:"password"`
|
||||
}
|
||||
if c.ShouldBind(&q) == nil {
|
||||
if q.Username == "" {
|
||||
c.String(http.StatusBadRequest, "Login data is null")
|
||||
} else {
|
||||
user := User{
|
||||
Username: q.Username,
|
||||
}
|
||||
orm.Take(&user)
|
||||
if user.Password == q.Password {
|
||||
c.JSON(http.StatusOK, map[string]string{"username": user.Username})
|
||||
} else {
|
||||
c.Status(http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.String(http.StatusBadRequest, "Unable to bind data")
|
||||
}
|
||||
})
|
||||
|
||||
r.GET("/user", func(c *gin.Context) {
|
||||
var q struct {
|
||||
Name string `form:"name"`
|
||||
}
|
||||
if c.ShouldBind(&q) == nil {
|
||||
user := User{
|
||||
Username: q.Name,
|
||||
}
|
||||
orm.Take(&user)
|
||||
fmt.Println(user)
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
||||
})
|
||||
|
||||
r.POST("/user", func(c *gin.Context) {
|
||||
var u User
|
||||
if c.ShouldBind(&u) == nil {
|
||||
orm.Create(&u)
|
||||
c.Status(http.StatusCreated)
|
||||
} else {
|
||||
fmt.Print("Could not bind model")
|
||||
}
|
||||
})
|
||||
|
||||
r.GET("/users/:id", func(c *gin.Context) {
|
||||
u := ExtractUser(orm, c)
|
||||
if u == nil {
|
||||
return
|
||||
}
|
||||
|
||||
requested := c.Param("id")
|
||||
if requested == "" {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
other := User{Username: requested}
|
||||
res := orm.Take(&other)
|
||||
if res.Error != nil {
|
||||
c.String(http.StatusInternalServerError, res.Error.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, other)
|
||||
})
|
||||
|
||||
r.POST("/plans", func(c *gin.Context) {
|
||||
u := ExtractUser(orm, c)
|
||||
if u == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var plan_req struct {
|
||||
Name string `json:"name" form:"name"`
|
||||
}
|
||||
c.Bind(&plan_req)
|
||||
var plan Plan = Plan{
|
||||
Name: plan_req.Name,
|
||||
Owner: u.Username,
|
||||
Members: []Member{
|
||||
{
|
||||
UserID: u.Username,
|
||||
Type: "user",
|
||||
Status: "ready",
|
||||
JoinCode: "owner",
|
||||
},
|
||||
},
|
||||
}
|
||||
result := orm.Create(&plan)
|
||||
|
||||
if result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, result.Error)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, plan_req)
|
||||
}
|
||||
})
|
||||
|
||||
r.GET("/plans", func(c *gin.Context) {
|
||||
u := ExtractUser(orm, c)
|
||||
if u == nil {
|
||||
return
|
||||
}
|
||||
plans, err := u.GetPlans(orm)
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, plans)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
r.GET("/plans/:id", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
Id uint `uri:"id"`
|
||||
}
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(orm, *user, params.Id)
|
||||
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, plan)
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
} else if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
r.GET("/plans/:id/members", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan_id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(orm, *user, uint(plan_id))
|
||||
members, err := plan.GetAllUsers(orm)
|
||||
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, members)
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
} else if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
r.POST("/plans/:id/members", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan_id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(orm, *user, uint(plan_id))
|
||||
|
||||
var new_member Member
|
||||
if err := c.ShouldBind(&new_member); err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = plan.AddMember(orm, &new_member)
|
||||
|
||||
if err == nil {
|
||||
c.JSON(http.StatusOK, new_member)
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
} else if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
} else {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
r.GET("/plans/:id/join", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan_id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
plan, err := GetPlan(orm, *user, uint(plan_id))
|
||||
if err != nil {
|
||||
c.Status(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
member, err := plan.GetMember(orm, user)
|
||||
var query struct {
|
||||
JoinCode string `form:"code"`
|
||||
}
|
||||
if c.ShouldBindQuery(&query) != nil || query.JoinCode == "" {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if member.Status != "pending" {
|
||||
c.String(http.StatusConflict, "User is not pending")
|
||||
return
|
||||
}
|
||||
if member.JoinCode == query.JoinCode {
|
||||
member.Status = "ready"
|
||||
err := orm.Model(&member).Update("status", member.Status).Error
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.String(http.StatusConflict, "Invalid join code")
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusOK)
|
||||
})
|
||||
|
||||
r.POST("/plans/:id/polls", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
Id uint `uri:"id"`
|
||||
}
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
return
|
||||
}
|
||||
|
||||
plan, err := GetPlan(orm, *user, params.Id)
|
||||
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
} else if errors.Is(err, ErrNotMember) {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
} else if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var poll_opts struct {
|
||||
Options string `json:"options"`
|
||||
}
|
||||
bind_result = c.Bind(&poll_opts)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
|
||||
poll := Poll{
|
||||
PlanID: plan.ID,
|
||||
Options: poll_opts.Options,
|
||||
}
|
||||
orm.Create(&poll)
|
||||
|
||||
c.JSON(http.StatusCreated, poll)
|
||||
})
|
||||
|
||||
r.GET("/plans/:id/polls", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
Id uint `uri:"id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var polls []Poll
|
||||
orm.Where("plan_id = ?", params.Id).Find(&polls)
|
||||
c.JSON(http.StatusOK, polls)
|
||||
})
|
||||
|
||||
r.GET("/polls/:poll_id", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
PollId uint `uri:"poll_id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
fmt.Println(params)
|
||||
|
||||
poll, _ := models.GetPoll(orm, *user, params.PollId)
|
||||
c.JSON(http.StatusOK, poll)
|
||||
})
|
||||
|
||||
r.GET("/polls/:poll_id/votes", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var params struct {
|
||||
PollId uint `uri:"poll_id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(¶ms)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
|
||||
var votes []Vote
|
||||
orm.Where("poll_id = ?", params.PollId).Find(&votes)
|
||||
c.JSON(http.StatusOK, &votes)
|
||||
})
|
||||
|
||||
r.POST("/polls/:poll_id/votes", func(c *gin.Context) {
|
||||
user := ExtractUser(orm, c)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var path_params struct {
|
||||
PollId uint `uri:"poll_id"`
|
||||
}
|
||||
|
||||
bind_result := c.BindUri(&path_params)
|
||||
if bind_result != nil {
|
||||
fmt.Println(bind_result)
|
||||
return
|
||||
}
|
||||
|
||||
poll, err := models.GetPoll(orm, *user, path_params.PollId)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var vote_params struct {
|
||||
Vote string `json:"vote"`
|
||||
}
|
||||
c.Bind(&vote_params)
|
||||
|
||||
if err := poll.SetVote(orm, *user, vote_params.Vote); err != nil {
|
||||
c.String(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
})
|
||||
|
||||
apis.BindAPIs(r, orm)
|
||||
r.Run()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue