aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorVidhu Kant Sharma <vidhukant@vidhukant.com>2025-10-11 20:55:48 +0530
committerVidhu Kant Sharma <vidhukant@vidhukant.com>2025-10-11 20:55:48 +0530
commitbc154857fb5569d7c1fa9785cc891cb927a6a156 (patch)
tree590c9f6a00a1b97b2ee45cfa5a767558089affe0
parent8a47978ca17d2f251d67d12b0e34fa26bb1e4ace (diff)
removed per-user itemsv0.17.0
-rw-r--r--auth/middleware.go2
-rw-r--r--customer/controller.go71
-rw-r--r--customer/customer.go3
-rw-r--r--customer/service.go7
-rw-r--r--customer/validators.go26
-rw-r--r--errors/errors.go4
-rw-r--r--errors/status.go6
-rw-r--r--invoice/controller.go229
-rw-r--r--invoice/invoice.go3
-rw-r--r--invoice/router.go4
-rw-r--r--invoice/service.go42
-rw-r--r--invoice/validators.go28
-rw-r--r--item/controller.go101
-rw-r--r--item/hooks.go13
-rw-r--r--item/item.go7
-rw-r--r--item/router.go1
-rw-r--r--item/service.go22
-rw-r--r--item/validators.go58
-rw-r--r--main.go2
-rw-r--r--user/validators.go45
20 files changed, 59 insertions, 615 deletions
diff --git a/auth/middleware.go b/auth/middleware.go
index 9a065d5..9ce5e12 100644
--- a/auth/middleware.go
+++ b/auth/middleware.go
@@ -70,8 +70,6 @@ func Authorize() gin.HandlerFunc {
return
}
- ctx.Set("UserID", claims.UserID)
-
ctx.Next()
}
}
diff --git a/customer/controller.go b/customer/controller.go
index f2704bd..83423da 100644
--- a/customer/controller.go
+++ b/customer/controller.go
@@ -31,17 +31,7 @@ func handleGetSingleCustomer (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var customer Customer
-
err = getCustomer(&customer, uint(id))
if err != nil {
ctx.Error(err)
@@ -49,14 +39,7 @@ func handleGetSingleCustomer (ctx *gin.Context) {
return
}
- if customer.UserID != userId {
- ctx.Error(e.ErrForbidden)
- ctx.Abort()
- return
- }
-
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": customer,
})
}
@@ -64,16 +47,7 @@ func handleGetSingleCustomer (ctx *gin.Context) {
func handleGetCustomers (ctx *gin.Context) {
var customers []Customer
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
- err := getCustomers(&customers, userId)
+ err := getCustomers(&customers)
if err != nil {
ctx.Error(err)
ctx.Abort()
@@ -81,7 +55,6 @@ func handleGetCustomers (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": customers,
})
}
@@ -90,26 +63,6 @@ func handleSaveCustomer (ctx *gin.Context) {
var customer Customer
ctx.Bind(&customer)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- customer.UserID = userId // necessary even when editing, just in case if UserID was ommitted in the request
-
- if customer.ID != 0 {
- // if customer is being edited, check ownership
- err := checkCustomerOwnership(customer.ID, userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
- }
-
err := customer.upsert()
if err != nil {
ctx.Error(err)
@@ -118,7 +71,6 @@ func handleSaveCustomer (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": customer,
})
}
@@ -133,23 +85,6 @@ func handleDelCustomer (ctx *gin.Context) {
var customer Customer
customer.ID = uint(id)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- customer.UserID = userId
-
- err = checkCustomerOwnership(customer.ID, customer.UserID)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
err = customer.del()
if err != nil {
ctx.Error(err)
@@ -157,7 +92,5 @@ func handleDelCustomer (ctx *gin.Context) {
return
}
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- })
+ ctx.JSON(http.StatusOK, nil)
}
diff --git a/customer/customer.go b/customer/customer.go
index 2303ae8..25c4645 100644
--- a/customer/customer.go
+++ b/customer/customer.go
@@ -21,7 +21,6 @@ import (
"gorm.io/gorm"
d "vidhukant.com/openbills/db"
u "vidhukant.com/openbills/util"
- "vidhukant.com/openbills/user"
)
var db *gorm.DB
@@ -45,8 +44,6 @@ type CustomerShippingAddress struct {
type Customer struct {
gorm.Model
- UserID uint `json:"-"`
- User user.User `json:"-"`
FirmName string
Gstin string
ContactName string
diff --git a/customer/service.go b/customer/service.go
index 8cd2bde..a0ed4dc 100644
--- a/customer/service.go
+++ b/customer/service.go
@@ -37,8 +37,8 @@ func getCustomer(customer *Customer, id uint) error {
return nil
}
-func getCustomers(customers *[]Customer, userId uint) error {
- res := db.Where("user_id = ?", userId).Find(&customers)
+func getCustomers(customers *[]Customer) error {
+ res := db.Find(&customers)
// TODO: handle potential errors
if res.Error != nil {
@@ -60,14 +60,13 @@ func (c *Customer) upsert() error {
}
func (c *Customer) del() error {
- res := db.Where("id = ? and user_id = ?", c.ID, c.UserID).Delete(c)
+ res := db.Where("id = ?", c.ID).Delete(c)
// TODO: handle potential errors
if res.Error != nil {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return e.ErrNotFound
}
diff --git a/customer/validators.go b/customer/validators.go
index b8c2a14..5693116 100644
--- a/customer/validators.go
+++ b/customer/validators.go
@@ -62,29 +62,3 @@ func (c *Customer) validate() error {
return nil
}
-
-func checkCustomerOwnership(customerId, userId uint) error {
- var customer Customer
- err := db.
- Select("id", "user_id").
- Where("id = ?", customerId).
- Find(&customer).
- Error
-
- // TODO: handle potential errors
- if err != nil {
- return err
- }
-
- // customer doesn't exist
- if customer.ID == 0 {
- return errors.ErrNotFound
- }
-
- // user doesn't own this customer
- if customer.UserID != userId {
- return errors.ErrForbidden
- }
-
- return nil
-}
diff --git a/errors/errors.go b/errors/errors.go
index 0d88490..17afdfe 100644
--- a/errors/errors.go
+++ b/errors/errors.go
@@ -62,11 +62,7 @@ var (
ErrCannotEditInvoice = errors.New("This Invoice Cannot Be Edited Now")
// 409
- ErrNonUniqueGSTIN = errors.New("GSTIN Must Be Unique")
- ErrNonUniquePhone = errors.New("Phone Number Is Already In Use")
- ErrNonUniqueEmail = errors.New("Email Address Is Already In Use")
ErrNonUniqueUsername = errors.New("Username Is Already In Use")
- ErrNonUniqueWebsite = errors.New("Website Is Already In Use")
ErrNonUniqueBrandName = errors.New("Brand Name Is Already In Use")
ErrNonUniqueBrandItem = errors.New("Item With Same Name And Brand Already Exists")
ErrNonUniqueInvoiceNumber = errors.New("Invoice Number Must Be Unique")
diff --git a/errors/status.go b/errors/status.go
index 47820b5..a874423 100644
--- a/errors/status.go
+++ b/errors/status.go
@@ -70,11 +70,7 @@ func StatusCodeFromErr(err error) int {
}
// 409
- if errors.Is(err, ErrNonUniqueGSTIN) ||
- errors.Is(err, ErrNonUniquePhone) ||
- errors.Is(err, ErrNonUniqueUsername) ||
- errors.Is(err, ErrNonUniqueEmail) ||
- errors.Is(err, ErrNonUniqueWebsite) ||
+ if errors.Is(err, ErrNonUniqueUsername) ||
errors.Is(err, ErrNonUniqueBrandName) ||
errors.Is(err, ErrNonUniqueInvoiceNumber) ||
errors.Is(err, ErrNonUniqueBrandItem) {
diff --git a/invoice/controller.go b/invoice/controller.go
index ad6df3e..b03ec22 100644
--- a/invoice/controller.go
+++ b/invoice/controller.go
@@ -32,17 +32,7 @@ func handleGetSingleInvoice (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var invoice Invoice
-
err = getInvoice(&invoice, uint(id))
if err != nil {
ctx.Error(err)
@@ -50,85 +40,36 @@ func handleGetSingleInvoice (ctx *gin.Context) {
return
}
- if invoice.UserID != userId {
- ctx.Error(e.ErrForbidden)
- ctx.Abort()
- return
- }
-
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": invoice,
})
}
-func handleGetInvoices (ctx *gin.Context) {
- var invoices []Invoice
-
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
- err := getInvoices(&invoices, userId, false)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- "data": invoices,
- })
-}
-
-func handleGetDrafts (ctx *gin.Context) {
- var invoices []Invoice
-
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
+func handleGetInvoices(getDrafts bool) func(*gin.Context) {
+ return func(ctx *gin.Context) {
+ var invoices []Invoice
- userId := uId.(uint)
+ err := getInvoices(&invoices, getDrafts)
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
- err := getInvoices(&invoices, userId, true)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
+ ctx.JSON(http.StatusOK, gin.H{
+ "data": invoices,
+ })
}
-
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- "data": invoices,
- })
}
func handleSaveInvoice (ctx *gin.Context) {
var invoice Invoice
ctx.Bind(&invoice)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- invoice.UserID = userId
-
// if invoice number is 0, generate one!
+ // (maybe the client didn't give us one)
if invoice.InvoiceNumber == 0 {
- n, err := getNewInvoiceNumber(invoice.UserID)
+ n, err := getNewInvoiceNumber()
if err != nil {
ctx.Error(err)
@@ -147,12 +88,12 @@ func handleSaveInvoice (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": invoice,
})
}
func handleDelInvoice (ctx *gin.Context) {
+ // TODO: only drafts can be deleted, non-drafts should be "cancelled"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.Error(e.ErrInvalidID)
@@ -163,23 +104,6 @@ func handleDelInvoice (ctx *gin.Context) {
var invoice Invoice
invoice.ID = uint(id)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- invoice.UserID = userId
-
- err = checkInvoiceOwnership(invoice.ID, invoice.UserID)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
err = invoice.del()
if err != nil {
ctx.Error(err)
@@ -187,9 +111,7 @@ func handleDelInvoice (ctx *gin.Context) {
return
}
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- })
+ ctx.JSON(http.StatusOK, nil)
}
// get items belonging to a certain invoice
@@ -201,22 +123,6 @@ func handleGetInvoiceItems (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
- err = checkInvoiceOwnership(uint(id), userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
var items []InvoiceItem
err = getInvoiceItems(&items, uint(id))
if err != nil {
@@ -226,12 +132,12 @@ func handleGetInvoiceItems (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": items,
})
}
func addItem (ctx *gin.Context) {
+ // TODO: only drafts can be edited
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.Error(e.ErrInvalidID)
@@ -239,27 +145,11 @@ func addItem (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var item InvoiceItem
ctx.Bind(&item)
item.InvoiceID = uint(id)
- err = checkInvoiceOwnership(item.InvoiceID, userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
err = item.upsert()
if err != nil {
ctx.Error(err)
@@ -267,13 +157,11 @@ func addItem (ctx *gin.Context) {
return
}
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- "data": item,
- })
+ ctx.JSON(http.StatusOK, nil)
}
func removeItem (ctx *gin.Context) {
+ // TODO: only drafts can be edited
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.Error(e.ErrInvalidID)
@@ -281,27 +169,9 @@ func removeItem (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var item InvoiceItem
item.ID = uint(id)
- invoiceId, err := getItemInvoice(item.ID, userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
- item.InvoiceID = invoiceId
-
err = item.del()
if err != nil {
ctx.Error(err)
@@ -309,10 +179,7 @@ func removeItem (ctx *gin.Context) {
return
}
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- "data": item,
- })
+ ctx.JSON(http.StatusOK, nil)
}
// get custom fields belonging to a certain invoice
@@ -324,22 +191,6 @@ func handleGetInvoiceCustomFields (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
- err = checkInvoiceOwnership(uint(id), userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
var cf []CustomField
err = getInvoiceCustomFields(&cf, uint(id))
if err != nil {
@@ -349,12 +200,12 @@ func handleGetInvoiceCustomFields (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": cf,
})
}
func addCustomField (ctx *gin.Context) {
+ // TODO: only drafts can be edited
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.Error(e.ErrInvalidID)
@@ -362,27 +213,10 @@ func addCustomField (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var cf CustomField
ctx.Bind(&cf)
-
cf.InvoiceID = uint(id)
- err = checkInvoiceOwnership(cf.InvoiceID, userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
err = cf.upsert()
if err != nil {
ctx.Error(err)
@@ -391,12 +225,12 @@ func addCustomField (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": cf,
})
}
func removeCustomField (ctx *gin.Context) {
+ // TODO: only drafts can be edited
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.Error(e.ErrInvalidID)
@@ -404,27 +238,9 @@ func removeCustomField (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var cf CustomField
cf.ID = uint(id)
- invoiceId, err := getCustomFieldInvoice(cf.ID, userId)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
- cf.InvoiceID = invoiceId
-
err = cf.del()
if err != nil {
ctx.Error(err)
@@ -433,7 +249,6 @@ func removeCustomField (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": cf,
})
}
diff --git a/invoice/invoice.go b/invoice/invoice.go
index 4397710..9fa931b 100644
--- a/invoice/invoice.go
+++ b/invoice/invoice.go
@@ -20,7 +20,6 @@ package invoice
import (
"gorm.io/gorm"
d "vidhukant.com/openbills/db"
- "vidhukant.com/openbills/user"
u "vidhukant.com/openbills/util"
i "vidhukant.com/openbills/item"
"time"
@@ -63,8 +62,6 @@ type CustomField struct {
type Invoice struct {
gorm.Model
- UserID uint `json:"-"`
- User user.User `json:"-"`
InvoiceDate time.Time
InvoiceNumber uint
BillingAddress InvoiceBillingAddress
diff --git a/invoice/router.go b/invoice/router.go
index febd8fd..f406786 100644
--- a/invoice/router.go
+++ b/invoice/router.go
@@ -24,8 +24,8 @@ import (
func Routes(route *gin.RouterGroup) {
g := route.Group("/invoice")
{
- g.GET("/", handleGetInvoices)
- g.GET("/draft", handleGetDrafts)
+ g.GET("/", handleGetInvoices(false))
+ g.GET("/draft", handleGetInvoices(true))
g.GET("/:id", handleGetSingleInvoice)
g.POST("/", handleSaveInvoice)
g.DELETE("/:id", handleDelInvoice)
diff --git a/invoice/service.go b/invoice/service.go
index 163b21e..55b1319 100644
--- a/invoice/service.go
+++ b/invoice/service.go
@@ -22,18 +22,12 @@ import (
)
// returns greatest invoice number + 1
-func getNewInvoiceNumber(userId uint) (uint, error) {
- var i uint
-
+func getNewInvoiceNumber() (uint, error) {
// check if number of invoices is 0
var count int64
- err := db.Model(&Invoice{}).
- Where("user_id = ?", userId).
- Count(&count).
- Error
-
+ err := db.Model(&Invoice{}).Count(&count).Error
if err != nil {
- return i, err
+ return 0, err
}
// if no records exist, then invoice number should be 1
@@ -45,7 +39,8 @@ func getNewInvoiceNumber(userId uint) (uint, error) {
// NOTE: if there are gaps in invoice numbers,
// they won't be filled and the series would continue
// from the greatest invoice number.
- row := db.Model(&Invoice{}).Where("user_id = ?", userId).Select("max(invoice_number)").Row()
+ var i uint
+ row := db.Model(&Invoice{}).Select("max(invoice_number)").Row()
err = row.Scan(&i)
return i + 1, err
@@ -66,8 +61,8 @@ func getInvoice(invoice *Invoice, id uint) error {
return nil
}
-func getInvoices(invoices *[]Invoice, userId uint, isDraft bool) error {
- res := db.Where("user_id = ? and is_draft = ?", userId, isDraft).Find(&invoices)
+func getInvoices(invoices *[]Invoice, isDraft bool) error {
+ res := db.Where("is_draft = ?", isDraft).Find(&invoices)
// TODO: handle potential errors
if res.Error != nil {
@@ -118,14 +113,13 @@ func (i *Invoice) upsert() error {
}
func (i *Invoice) del() error {
- res := db.Where("id = ? and user_id = ?", i.ID, i.UserID).Delete(i)
+ res := db.Where("id = ?", i.ID).Delete(i)
// TODO: handle potential errors
if res.Error != nil {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return e.ErrNotFound
}
@@ -133,8 +127,7 @@ func (i *Invoice) del() error {
return nil
}
-// also checks for ownership
-func getItemInvoice(itemId, userId uint) (uint, error) {
+func getItemInvoice(itemId uint) (uint, error) {
var invoiceId uint
res := db.
Model(&InvoiceItem{}).
@@ -151,17 +144,10 @@ func getItemInvoice(itemId, userId uint) (uint, error) {
return invoiceId, e.ErrNotFound
}
- err := checkInvoiceOwnership(invoiceId, userId)
-
- if err != nil {
- return invoiceId, err
- }
-
return invoiceId, nil
}
-// also checks for ownership
-func getCustomFieldInvoice(fieldId, userId uint) (uint, error) {
+func getCustomFieldInvoice(fieldId uint) (uint, error) {
var invoiceId uint
res := db.
Model(&CustomField{}).
@@ -178,12 +164,6 @@ func getCustomFieldInvoice(fieldId, userId uint) (uint, error) {
return invoiceId, e.ErrNotFound
}
- err := checkInvoiceOwnership(invoiceId, userId)
-
- if err != nil {
- return invoiceId, err
- }
-
return invoiceId, nil
}
@@ -195,7 +175,6 @@ func (i *InvoiceItem) del() error {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return e.ErrNotFound
}
@@ -211,7 +190,6 @@ func (c *CustomField) del() error {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return e.ErrNotFound
}
diff --git a/invoice/validators.go b/invoice/validators.go
index 9f145dc..1c39cbe 100644
--- a/invoice/validators.go
+++ b/invoice/validators.go
@@ -24,7 +24,7 @@ import (
func (i *Invoice) validate() error {
var count int64
err := db.Model(&Invoice{}).
- Where("user_id = ? and invoice_number = ?", i.UserID, i.InvoiceNumber).
+ Where("invoice_number = ?", i.InvoiceNumber).
Count(&count).
Error
@@ -59,29 +59,3 @@ func isDraft(invoiceId uint) (bool, error) {
return invoice.IsDraft, nil
}
-
-func checkInvoiceOwnership(invoiceId, userId uint) error {
- var invoice Invoice
- err := db.
- Select("id", "user_id").
- Where("id = ?", invoiceId).
- Find(&invoice).
- Error
-
- // TODO: handle potential errors
- if err != nil {
- return err
- }
-
- // invoice doesn't exist
- if invoice.ID == 0 {
- return errors.ErrNotFound
- }
-
- // user doesn't own this invoice
- if invoice.UserID != userId {
- return errors.ErrForbidden
- }
-
- return nil
-}
diff --git a/item/controller.go b/item/controller.go
index 9993688..bb2eb94 100644
--- a/item/controller.go
+++ b/item/controller.go
@@ -31,17 +31,8 @@ func handleGetBrandItems (ctx *gin.Context) {
return
}
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
var items []SavedItem
- err = getBrandItems(&items, uint(id), userId)
+ err = getBrandItems(&items, uint(id))
if err != nil {
ctx.Error(err)
ctx.Abort()
@@ -49,7 +40,6 @@ func handleGetBrandItems (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": items,
})
}
@@ -57,16 +47,7 @@ func handleGetBrandItems (ctx *gin.Context) {
func handleGetBrands (ctx *gin.Context) {
var brands []Brand
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
- err := getBrands(&brands, userId)
+ err := getBrands(&brands)
if err != nil {
ctx.Error(err)
ctx.Abort()
@@ -74,7 +55,6 @@ func handleGetBrands (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": brands,
})
}
@@ -83,16 +63,6 @@ func handleSaveBrand (ctx *gin.Context) {
var brand Brand
ctx.Bind(&brand)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- brand.UserID = userId
-
err := brand.upsert()
if err != nil {
ctx.Error(err)
@@ -101,7 +71,6 @@ func handleSaveBrand (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": brand,
})
}
@@ -116,24 +85,6 @@ func handleDelBrand (ctx *gin.Context) {
var brand Brand
brand.ID = uint(id)
-
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- brand.UserID = userId
-
- err = checkBrandOwnership(brand.ID, brand.UserID)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
err = brand.del()
if err != nil {
ctx.Error(err)
@@ -141,24 +92,13 @@ func handleDelBrand (ctx *gin.Context) {
return
}
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- })
+ ctx.JSON(http.StatusOK, nil)
}
func handleGetItems (ctx *gin.Context) {
var items []SavedItem
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
-
- err := getItems(&items, userId)
+ err := getItems(&items)
if err != nil {
ctx.Error(err)
ctx.Abort()
@@ -166,7 +106,6 @@ func handleGetItems (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": items,
})
}
@@ -175,16 +114,6 @@ func handleSaveItem (ctx *gin.Context) {
var item SavedItem
ctx.Bind(&item)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- item.UserID = userId
-
err := item.upsert()
if err != nil {
ctx.Error(err)
@@ -193,7 +122,6 @@ func handleSaveItem (ctx *gin.Context) {
}
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": item,
})
}
@@ -208,23 +136,6 @@ func handleDelItem (ctx *gin.Context) {
var item SavedItem
item.ID = uint(id)
- uId, ok := ctx.Get("UserID")
- if !ok {
- ctx.Error(e.ErrUnauthorized)
- ctx.Abort()
- return
- }
-
- userId := uId.(uint)
- item.UserID = userId
-
- err = checkItemOwnership(item.ID, item.UserID)
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
err = item.del()
if err != nil {
ctx.Error(err)
@@ -232,7 +143,5 @@ func handleDelItem (ctx *gin.Context) {
return
}
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- })
+ ctx.JSON(http.StatusOK, nil)
}
diff --git a/item/hooks.go b/item/hooks.go
index 74b6860..5056cb1 100644
--- a/item/hooks.go
+++ b/item/hooks.go
@@ -20,22 +20,11 @@ package item
import (
"gorm.io/gorm"
"vidhukant.com/openbills/errors"
- e "errors"
)
func (i *SavedItem) BeforeSave(tx *gorm.DB) error {
var err error
- // also checks if brand actually exists
- err = checkBrandOwnership(i.BrandID, i.UserID)
- if err != nil {
- if e.Is(err, errors.ErrBrandNotFound) {
- // this error has a better error message for this case
- return errors.ErrBrandNotFound
- }
- return err
- }
-
err = i.validate()
if err != nil {
return err
@@ -60,7 +49,7 @@ func (b *Brand) BeforeDelete(tx *gorm.DB) error {
}
// delete all items
- err := db.Where("brand_id = ? and user_id = ?", b.ID, b.UserID).Delete(&SavedItem{}).Error
+ err := db.Where("brand_id = ?", b.ID).Delete(&SavedItem{}).Error
if err != nil {
return err
}
diff --git a/item/item.go b/item/item.go
index 3f911fa..617a662 100644
--- a/item/item.go
+++ b/item/item.go
@@ -20,7 +20,6 @@ package item
import (
"gorm.io/gorm"
d "vidhukant.com/openbills/db"
- "vidhukant.com/openbills/user"
)
var db *gorm.DB
@@ -32,8 +31,6 @@ func init() {
type Brand struct {
gorm.Model
- UserID uint `json:"-"`
- User user.User `json:"-"`
Name string
}
@@ -41,7 +38,7 @@ type Item struct {
Name string
Description string
HSN string
- UnitOfMeasure string // TODO: probably has to be a custom type
+ UnitOfMeasure string
UnitPrice string // float
GSTPercentage string // float
}
@@ -51,6 +48,4 @@ type SavedItem struct {
Item
BrandID uint
Brand Brand
- UserID uint `json:"-"`
- User user.User `json:"-"`
}
diff --git a/item/router.go b/item/router.go
index fab973f..b953d09 100644
--- a/item/router.go
+++ b/item/router.go
@@ -33,7 +33,6 @@ func Routes(route *gin.RouterGroup) {
i := route.Group("/item")
{
i.GET("/", handleGetItems)
- //i.GET("/:id", handleGetBrandItems)
i.POST("/", handleSaveItem)
i.DELETE("/:id", handleDelItem)
}
diff --git a/item/service.go b/item/service.go
index 80faff0..0b2afaf 100644
--- a/item/service.go
+++ b/item/service.go
@@ -21,12 +21,7 @@ import (
"vidhukant.com/openbills/errors"
)
-func getBrandItems(items *[]SavedItem, id, userId uint) error {
- err := checkBrandOwnership(id, userId)
- if err != nil {
- return err
- }
-
+func getBrandItems(items *[]SavedItem, id uint) error {
// get items
res := db.Model(&SavedItem{}).Where("brand_id = ?", id).Find(&items)
@@ -35,7 +30,6 @@ func getBrandItems(items *[]SavedItem, id, userId uint) error {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return errors.ErrEmptyResponse
}
@@ -43,8 +37,8 @@ func getBrandItems(items *[]SavedItem, id, userId uint) error {
return nil
}
-func getBrands(brands *[]Brand, userId uint) error {
- res := db.Where("user_id = ?", userId).Find(&brands)
+func getBrands(brands *[]Brand) error {
+ res := db.Find(&brands)
// TODO: handle potential errors
if res.Error != nil {
@@ -66,14 +60,13 @@ func (b *Brand) upsert() error {
func (b *Brand) del() error {
// delete brand
- res := db.Where("id = ? and user_id = ?", b.ID, b.UserID).Delete(b)
+ res := db.Where("id = ?", b.ID).Delete(b)
// TODO: handle potential errors
if res.Error != nil {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return errors.ErrNotFound
}
@@ -81,8 +74,8 @@ func (b *Brand) del() error {
return nil
}
-func getItems(items *[]SavedItem, userId uint) error {
- res := db.Where("user_id = ?", userId).Preload("Brand").Find(&items)
+func getItems(items *[]SavedItem) error {
+ res := db.Preload("Brand").Find(&items)
// TODO: handle potential errors
if res.Error != nil {
@@ -103,14 +96,13 @@ func (i *SavedItem) upsert() error {
}
func (i *SavedItem) del() error {
- res := db.Where("id = ? and user_id = ?", i.ID, i.UserID).Delete(i)
+ res := db.Where("id = ?", i.ID).Delete(i)
// TODO: handle potential errors
if res.Error != nil {
return res.Error
}
- // returns 404 if either row doesn't exist or if the user doesn't own it
if res.RowsAffected == 0 {
return errors.ErrNotFound
}
diff --git a/item/validators.go b/item/validators.go
index b808ae4..63c254f 100644
--- a/item/validators.go
+++ b/item/validators.go
@@ -32,11 +32,11 @@ func (b *Brand) validate() error {
return errors.ErrEmptyBrandName
}
- // make sure GSTIN is unique
+ // make sure brand name is unique
var count int64
err := db.Model(&Brand{}).
Select("name").
- Where("name = ? and user_id = ?", b.Name, b.UserID).
+ Where("name = ?", b.Name).
Count(&count).
Error
@@ -75,7 +75,7 @@ func (i *SavedItem) validate() error {
var count int64
err = db.Model(&SavedItem{}).
Select("name, brand_id").
- Where("brand_id = ? and name = ? and user_id = ?", i.BrandID, i.Name, i.UserID).
+ Where("brand_id = ? and name = ?", i.BrandID, i.Name).
Count(&count).
Error
@@ -89,55 +89,3 @@ func (i *SavedItem) validate() error {
return nil
}
-
-func checkBrandOwnership(brandId, userId uint) error {
- var brand Brand
- err := db.
- Select("id", "user_id").
- Where("id = ?", brandId).
- Find(&brand).
- Error
-
- // TODO: handle potential errors
- if err != nil {
- return err
- }
-
- // brand doesn't exist
- if brand.ID == 0 {
- return errors.ErrNotFound
- }
-
- // user doesn't own this brand
- if brand.UserID != userId {
- return errors.ErrForbidden
- }
-
- return nil
-}
-
-func checkItemOwnership(itemId, userId uint) error {
- var item SavedItem
- err := db.
- Select("id", "user_id").
- Where("id = ?", itemId).
- Find(&item).
- Error
-
- // TODO: handle potential errors
- if err != nil {
- return err
- }
-
- // item doesn't exist
- if item.ID == 0 {
- return errors.ErrNotFound
- }
-
- // user doesn't own this item
- if item.UserID != userId {
- return errors.ErrForbidden
- }
-
- return nil
-}
diff --git a/main.go b/main.go
index bfa17d4..9fe3f44 100644
--- a/main.go
+++ b/main.go
@@ -38,7 +38,7 @@ import (
"log"
)
-const OPENBILLS_VERSION = "v0.16.0"
+const OPENBILLS_VERSION = "v0.17.0"
func init() {
if !viper.GetBool("debug_mode") {
diff --git a/user/validators.go b/user/validators.go
index b54457f..e497122 100644
--- a/user/validators.go
+++ b/user/validators.go
@@ -19,7 +19,6 @@ package user
import (
"strings"
- e "errors"
"github.com/spf13/viper"
"vidhukant.com/openbills/errors"
"vidhukant.com/openbills/util"
@@ -59,41 +58,6 @@ func validateUsername(username string) error {
return nil
}
-// NOTE: very inefficient and really really really dumb but it works
-// TODO: find a better (or even a remotely good) way
-func validateUserField(field, value string) error {
- if value != "" {
- var count int64
- err := db.Model(&User{}).
- Where(field + " = ?", value).
- Count(&count).
- Error
-
- if err != nil {
- return err
- }
-
- if count > 0 {
- switch(field) {
- case "username":
- return errors.ErrNonUniqueUsername
- case "phone":
- return errors.ErrNonUniquePhone
- case "email":
- return errors.ErrNonUniqueEmail
- case "website":
- return errors.ErrNonUniqueWebsite
- case "gstin":
- return errors.ErrNonUniqueGSTIN
- default:
- return e.New(field + " is not unique")
- }
- }
- }
-
- return nil
-}
-
func (u *User) validate() error {
u.Username = strings.TrimSpace(u.Username)
u.Email = strings.TrimSpace(u.Email)
@@ -102,8 +66,6 @@ func (u *User) validate() error {
u.Gstin = strings.TrimSpace(u.Gstin)
u.IsVerified = false
- // TODO: validate username length and stuff
-
// don't validate if GSTIN is empty
if u.Gstin != "" && !util.ValidateGstin(u.Gstin) {
return errors.ErrInvalidGSTIN
@@ -146,12 +108,5 @@ func (u *User) validate() error {
return err
}
- for _, i := range [][]string{{"username", u.Username}, {"email", u.Email}, {"website", u.Website}, {"gstin", u.Gstin}, {"phone", u.Phone}} {
- err := validateUserField(i[0], i[1])
- if err != nil {
- return err
- }
- }
-
return nil
}