Compare commits

..

No commits in common. "155deb889cc5d0dc30f8bff6e499a9606c239415" and "48f7b8258e162ee25d6c1a2195cd130a9abb2d47" have entirely different histories.

16 changed files with 253 additions and 115 deletions

View File

@ -6,10 +6,10 @@ import (
"github.com/swaggo/files" "github.com/swaggo/files"
"github.com/swaggo/gin-swagger" "github.com/swaggo/gin-swagger"
docs "git.qowevisa.me/Qowevisa/fin-check-api/docs" docs "git.qowevisa.me/Qowevisa/gonuts/docs"
"git.qowevisa.me/Qowevisa/fin-check-api/handlers" "git.qowevisa.me/Qowevisa/gonuts/handlers"
"git.qowevisa.me/Qowevisa/fin-check-api/middleware" "git.qowevisa.me/Qowevisa/gonuts/middleware"
"git.qowevisa.me/Qowevisa/fin-check-api/tokens" "git.qowevisa.me/Qowevisa/gonuts/tokens"
"github.com/gin-contrib/cors" "github.com/gin-contrib/cors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -95,5 +95,5 @@ func main() {
}) })
go tokens.StartTokens() go tokens.StartTokens()
r.Run("127.0.0.1:3000") r.Run("127.0.0.1:3001")
} }

View File

@ -19,18 +19,3 @@ type Debt struct {
UserID uint UserID uint
User *User User *User
} }
// Implements db.UserIdentifiable:1
func (d Debt) GetID() uint {
return d.ID
}
// Implements db.UserIdentifiable:2
func (d Debt) GetUserID() uint {
return d.UserID
}
// Implements db.UserIdentifiable:3
func (d *Debt) SetUserID(id uint) {
d.UserID = id
}

View File

@ -4,14 +4,9 @@ import "gorm.io/gorm"
type ItemBought struct { type ItemBought struct {
gorm.Model gorm.Model
ItemID uint ItemID uint
Item *Item Item *Item
PaymentID uint Quantity uint
Payment *Payment PaymentID uint
TypeID uint Payment *Payment
Type *Type
Quantity uint
TotalCost uint64
MetricType uint8
MetricValue uint64
} }

View File

@ -13,7 +13,7 @@ type ItemPrice struct {
Item *Item Item *Item
Price uint64 Price uint64
ValidFrom time.Time ValidFrom time.Time
ValidTo time.Time IsValid bool `gorm:"default:true"`
} }
var ( var (

View File

@ -13,9 +13,7 @@ type Payment struct {
Card *Card Card *Card
CategoryID uint CategoryID uint
Category *Category Category *Category
UserID uint Name string
User *User
Title string
Descr string Descr string
Note string Note string
Items []ItemBought Items []ItemBought

2
go.mod
View File

@ -1,4 +1,4 @@
module git.qowevisa.me/Qowevisa/fin-check-api module git.qowevisa.me/Qowevisa/gonuts
go 1.20 go 1.20

View File

@ -1,8 +1,8 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/fin-check-api/db" "git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,8 +1,8 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/fin-check-api/db" "git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,8 +1,12 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/fin-check-api/db" "fmt"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "strconv"
"git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/gonuts/types"
"git.qowevisa.me/Qowevisa/gonuts/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -16,23 +20,60 @@ import (
// @Success 200 {object} types.DbDebt // @Success 200 {object} types.DbDebt
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 401 {object} types.ErrorResponse // @Failure 401 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/:id [get] // @Router /debt/:id [get]
func DebtGetId(c *gin.Context) { func DebtGetId(c *gin.Context) {
GetHandler(func(inp *db.Debt) types.DbDebt { userIDAny, exists := c.Get("UserID")
return types.DbDebt{ if !exists {
ID: inp.ID, c.JSON(500, types.ErrorResponse{Message: "Internal error 001"})
CardID: inp.CardID, return
Comment: inp.Comment, }
Value: inp.Value,
IOwe: inp.IOwe, var userID uint
Date: inp.Date, if userIDVal, ok := userIDAny.(uint); !ok {
DateEnd: inp.DateEnd, c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
Finished: inp.Finished, return
} } else {
})(c) userID = userIDVal
}
idStr := c.Param("id")
var id uint
if idVal, err := strconv.ParseUint(idStr, 10, 32); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
} else {
id = uint(idVal)
}
var dbDebt db.Debt
dbc := db.Connect()
if err := dbc.Find(&dbDebt, id).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ003"})
return
}
if dbDebt.UserID != userID {
c.JSON(401, types.ErrorResponse{Message: "This debt.id is not yours, you sneaky."})
return
}
ret := types.DbDebt{
ID: dbDebt.ID,
CardID: dbDebt.CardID,
Comment: dbDebt.Comment,
Value: dbDebt.Value,
IOwe: dbDebt.IOwe,
Date: dbDebt.Date,
DateEnd: dbDebt.DateEnd,
Finished: dbDebt.Finished,
UserID: dbDebt.UserID,
}
c.JSON(200, ret)
} }
// @Summary Get debt by id // @Summary Get debt by id
@ -44,22 +85,60 @@ func DebtGetId(c *gin.Context) {
// @Param debt body types.DbDebt true "Debt" // @Param debt body types.DbDebt true "Debt"
// @Success 200 {object} types.Message // @Success 200 {object} types.Message
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/add [post] // @Router /debt/add [post]
func DebtAdd(c *gin.Context) { func DebtAdd(c *gin.Context) {
debt := &db.Debt{} userIDAny, exists := c.Get("UserID")
CreateHandler(debt, if !exists {
func(src types.DbDebt, dst *db.Debt) { c.JSON(500, types.ErrorResponse{Message: "Internal error 001"})
dst.CardID = src.CardID return
dst.Comment = src.Comment }
dst.Value = src.Value
dst.IOwe = src.IOwe var userID uint
dst.Date = src.Date if userIDVal, ok := userIDAny.(uint); !ok {
dst.DateEnd = src.DateEnd c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
dst.Finished = src.Finished return
}, } else {
)(c) userID = userIDVal
}
var debt types.DbDebt
if err := c.ShouldBindJSON(&debt); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
}
if debt.UserID != 0 && userID != debt.UserID {
c.JSON(403, types.ErrorResponse{Message: "UserID in body is different than yours!"})
}
if debt.UserID == 0 {
debt.UserID = userID
}
dbDebt := &db.Debt{
CardID: debt.CardID,
Comment: debt.Comment,
Value: debt.Value,
IOwe: debt.IOwe,
Date: debt.Date,
DateEnd: debt.DateEnd,
Finished: debt.Finished,
UserID: debt.UserID,
}
dbc := db.Connect()
if err := dbc.Create(&dbDebt).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ004"})
return
}
msg := types.Message{
Message: fmt.Sprintf("Debt with id %d was successfully created!", dbDebt.ID),
}
c.JSON(200, msg)
} }
// @Summary Edit debt by id // @Summary Edit debt by id
@ -73,34 +152,72 @@ func DebtAdd(c *gin.Context) {
// @Success 200 {object} types.DbDebt // @Success 200 {object} types.DbDebt
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 401 {object} types.ErrorResponse // @Failure 401 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/edit/:id [put] // @Router /debt/edit/:id [put]
func DebtPutId(c *gin.Context) { func DebtPutId(c *gin.Context) {
UpdateHandler( userIDAny, exists := c.Get("UserID")
// Filter used to apply only needed changes from srt to dst before updating dst if !exists {
func(src types.DbDebt, dst *db.Debt) { c.JSON(500, types.ErrorResponse{Message: "Internal error 001"})
dst.CardID = src.CardID return
dst.Comment = src.Comment }
dst.Value = src.Value
dst.IOwe = src.IOwe var userID uint
dst.Date = src.Date if userIDVal, ok := userIDAny.(uint); !ok {
dst.DateEnd = src.DateEnd c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
dst.Finished = src.Finished return
}, } else {
func(inp *db.Debt) types.DbDebt { userID = userIDVal
return types.DbDebt{ }
ID: inp.ID,
CardID: inp.CardID, idStr := c.Param("id")
Comment: inp.Comment, var id uint
Value: inp.Value, if idVal, err := strconv.ParseUint(idStr, 10, 32); err != nil {
IOwe: inp.IOwe, c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
Date: inp.Date, return
DateEnd: inp.DateEnd, } else {
Finished: inp.Finished, id = uint(idVal)
} }
})(c)
var dbDebt db.Debt
dbc := db.Connect()
if err := dbc.Find(&dbDebt, id).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ003"})
return
}
if dbDebt.UserID != userID {
c.JSON(401, types.ErrorResponse{Message: "This debt.id is not yours, you sneaky."})
return
}
var debt types.DbDebt
if err := c.ShouldBindJSON(&debt); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
}
utils.MergeNonZeroFields(debt, dbDebt)
if err := dbc.Save(dbDebt).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
ret := types.DbDebt{
ID: dbDebt.ID,
CardID: dbDebt.CardID,
Comment: dbDebt.Comment,
Value: dbDebt.Value,
IOwe: dbDebt.IOwe,
Date: dbDebt.Date,
DateEnd: dbDebt.DateEnd,
Finished: dbDebt.Finished,
UserID: dbDebt.UserID,
}
c.JSON(200, ret)
} }
// @Summary Delete debt by id // @Summary Delete debt by id
@ -113,10 +230,62 @@ func DebtPutId(c *gin.Context) {
// @Success 200 {object} types.DbDebt // @Success 200 {object} types.DbDebt
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 401 {object} types.ErrorResponse // @Failure 401 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/delete/:id [delete] // @Router /debt/delete/:id [delete]
func DebtDeleteId(c *gin.Context) { func DebtDeleteId(c *gin.Context) {
DeleteHandler[*db.Debt]()(c) userIDAny, exists := c.Get("UserID")
if !exists {
c.JSON(500, types.ErrorResponse{Message: "Internal error 001"})
return
}
var userID uint
if userIDVal, ok := userIDAny.(uint); !ok {
c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
return
} else {
userID = userIDVal
}
idStr := c.Param("id")
var id uint
if idVal, err := strconv.ParseUint(idStr, 10, 32); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
} else {
id = uint(idVal)
}
var dbDebt db.Debt
dbc := db.Connect()
if err := dbc.Find(&dbDebt, id).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ003"})
return
}
if dbDebt.UserID != userID {
c.JSON(401, types.ErrorResponse{Message: "This debt.id is not yours, you sneaky."})
return
}
if err := dbc.Delete(dbDebt).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
ret := types.DbDebt{
ID: dbDebt.ID,
CardID: dbDebt.CardID,
Comment: dbDebt.Comment,
Value: dbDebt.Value,
IOwe: dbDebt.IOwe,
Date: dbDebt.Date,
DateEnd: dbDebt.DateEnd,
Finished: dbDebt.Finished,
UserID: dbDebt.UserID,
}
c.JSON(200, ret)
} }

View File

@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"git.qowevisa.me/Qowevisa/fin-check-api/db" "git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"git.qowevisa.me/Qowevisa/fin-check-api/utils" "git.qowevisa.me/Qowevisa/gonuts/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,7 +1,7 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,8 +1,8 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/fin-check-api/db" "git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -3,9 +3,9 @@ package handlers
import ( import (
"log" "log"
"git.qowevisa.me/Qowevisa/fin-check-api/db" "git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/fin-check-api/tokens" "git.qowevisa.me/Qowevisa/gonuts/tokens"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -3,8 +3,8 @@ package handlers
import ( import (
"fmt" "fmt"
"git.qowevisa.me/Qowevisa/fin-check-api/db" "git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -3,8 +3,8 @@ package middleware
import ( import (
"strings" "strings"
"git.qowevisa.me/Qowevisa/fin-check-api/tokens" "git.qowevisa.me/Qowevisa/gonuts/tokens"
"git.qowevisa.me/Qowevisa/fin-check-api/types" "git.qowevisa.me/Qowevisa/gonuts/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -47,6 +47,7 @@ type DbDebt struct {
Date time.Time `json:"date" example:"29/11/2001 12:00"` Date time.Time `json:"date" example:"29/11/2001 12:00"`
DateEnd time.Time `json:"date_end" example:"29/12/2001 12:00"` DateEnd time.Time `json:"date_end" example:"29/12/2001 12:00"`
Finished bool `json:"finished" example:"false"` Finished bool `json:"finished" example:"false"`
UserID uint `json:"user_id" example:"1"`
} }
type DbIncome struct { type DbIncome struct {
@ -64,13 +65,3 @@ type DbType struct {
Comment string `json:"comment" example:""` Comment string `json:"comment" example:""`
Color string `json:"color" example:"red"` Color string `json:"color" example:"red"`
} }
type DbPayment struct {
ID uint `json:"id" example:"1"`
CardID uint `json:"card_id" example:"1"`
CategoryID uint `json:"category_id" example:"1"`
Title string `json:"title" example:"Veggies"`
Descr string `json:"description" example:""`
Note string `json:"not" example:"I'm a teapot"`
Date time.Time `json:"date" example:"29/11/2001 12:00"`
}