aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--conf/conf.go6
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--main.go7
-rw-r--r--openbills.toml3
-rw-r--r--user/controller.go92
-rw-r--r--user/router.go4
-rw-r--r--user/service.go21
-rw-r--r--user/user.go22
10 files changed, 143 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index bbd55b1..8a33b00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/openbills
.env
+/data
diff --git a/conf/conf.go b/conf/conf.go
index 7531e4f..843bbea 100644
--- a/conf/conf.go
+++ b/conf/conf.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@ import (
"log"
)
+// TODO: check if openbills has read/write access to uploads dir
+// TODO: data.upload_dir must have a trailing /
func validateConf() {
ok := true
log.Println("\x1b[46m\x1b[30m[info]\x1b[0m Checking errors in config file...")
@@ -99,6 +101,8 @@ func init() {
viper.SetDefault("cryptography.password_hashing_cost", bcrypt.DefaultCost)
+ viper.SetDefault("data.upload_dir", "./data/")
+
validateConf()
log.Printf("\x1b[46m\x1b[30m[info]\x1b[0m Loaded Config \"%s\"\n", viper.ConfigFileUsed())
}
diff --git a/go.mod b/go.mod
index 576ab67..6ad6c01 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@ go 1.21.0
require (
github.com/gin-gonic/gin v1.9.1
- github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang-jwt/jwt/v5 v5.0.0
+ github.com/google/uuid v1.1.2
github.com/spf13/viper v1.16.0
golang.org/x/crypto v0.9.0
gorm.io/driver/mysql v1.5.1
diff --git a/go.sum b/go.sum
index f4b69b3..baef224 100644
--- a/go.sum
+++ b/go.sum
@@ -86,8 +86,6 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
-github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -145,6 +143,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
diff --git a/main.go b/main.go
index b1150d4..dcac46e 100644
--- a/main.go
+++ b/main.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -38,7 +38,7 @@ import (
"log"
)
-const OPENBILLS_VERSION = "v0.9.0"
+const OPENBILLS_VERSION = "v0.10.0"
func init() {
if !viper.GetBool("debug_mode") {
@@ -49,6 +49,9 @@ func init() {
func main() {
r := gin.New()
r.SetTrustedProxies([]string{"127.0.0.1"})
+ r.MaxMultipartMemory = 4 << 20
+
+ r.Static("/pub/", viper.GetString("data.upload_dir"))
r.GET("/info", serverInfo)
diff --git a/openbills.toml b/openbills.toml
index f10f666..0742aaf 100644
--- a/openbills.toml
+++ b/openbills.toml
@@ -26,3 +26,6 @@ max_username_length = 32
password_hashing_cost = 14
auth_key = "22ELiOfHn19s0z1WWgsOT9RupghRYrXm"
refresh_key = "22ELjsdlfkjalsdfjalsdjflajsdfljaiOfHn19s0z1WWgsOT9RupghRYrXm"
+
+[data]
+upload_dir = "./data/"
diff --git a/user/controller.go b/user/controller.go
index 15061cc..1dc85da 100644
--- a/user/controller.go
+++ b/user/controller.go
@@ -20,6 +20,8 @@ package user
import (
e "vidhukant.com/openbills/errors"
"github.com/gin-gonic/gin"
+ "github.com/google/uuid"
+ "github.com/spf13/viper"
"net/http"
)
@@ -51,6 +53,96 @@ func handleGetUser (ctx *gin.Context) {
})
}
+func handleUploadLogo(ctx *gin.Context) {
+ var user User
+
+ uId, ok := ctx.Get("UserID")
+ if !ok {
+ ctx.Error(e.ErrUnauthorized)
+ ctx.Abort()
+ return
+ }
+
+ userId := uId.(uint)
+ user.ID = userId
+
+ // TODO: handle potential errors
+ file, err := ctx.FormFile("logo")
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
+
+ dest := uuid.New().String()
+
+ // TODO: handle potential errors
+ err = ctx.SaveUploadedFile(file, viper.GetString("data.upload_dir") + dest)
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
+
+ // TODO: delete old file (if any)
+ err = user.update(map[string]interface{}{"logo_file": dest})
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
+
+ ctx.JSON(http.StatusOK, gin.H{
+ "message": "success",
+ })
+}
+
+func handleUploadSignature(ctx *gin.Context) {
+ var user User
+
+ uId, ok := ctx.Get("UserID")
+ if !ok {
+ ctx.Error(e.ErrUnauthorized)
+ ctx.Abort()
+ return
+ }
+
+ userId := uId.(uint)
+ user.ID = userId
+
+ // TODO: handle potential errors
+ file, err := ctx.FormFile("signature")
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
+
+ dest := uuid.New().String()
+
+ // TODO: handle potential errors
+ err = ctx.SaveUploadedFile(file, viper.GetString("data.upload_dir") + dest)
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
+
+ // TODO: delete old file (if any)
+ err = user.update(map[string]interface{}{"signature_file": dest})
+ if err != nil {
+ ctx.Error(err)
+ ctx.Abort()
+ return
+ }
+
+ ctx.JSON(http.StatusOK, gin.H{
+ "message": "success",
+ })
+}
+
+// TODO: fix this stuff
+// also add some kind of 2 factor verification
func handleDelUser (ctx *gin.Context) {
id := uint(1) // get from JWT
diff --git a/user/router.go b/user/router.go
index 8a9ad86..d9fa7e0 100644
--- a/user/router.go
+++ b/user/router.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,5 +25,7 @@ func Routes(route *gin.RouterGroup) {
g := route.Group("/user")
{
g.GET("/", handleGetUser)
+ g.POST("/logo", handleUploadLogo)
+ g.POST("/signature", handleUploadSignature)
}
}
diff --git a/user/service.go b/user/service.go
index 4544cb4..222df4a 100644
--- a/user/service.go
+++ b/user/service.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -75,3 +75,22 @@ func (u *User) del() error {
return nil
}
+
+func (u *User) update(changes map[string]interface{}) error {
+ res := db.Model(&u).
+ Omit("email").
+ Omit("password").
+ Omit("username").
+ Updates(changes)
+
+ // TODO: handle potential errors
+ if res.Error != nil {
+ return res.Error
+ }
+
+ if res.RowsAffected == 0 {
+ return e.ErrNotFound
+ }
+
+ return nil
+}
diff --git a/user/user.go b/user/user.go
index 726c5c2..b130ab9 100644
--- a/user/user.go
+++ b/user/user.go
@@ -40,17 +40,19 @@ func init() {
type User struct {
gorm.Model
u.Address
- FullName string
- FirmName string
- Gstin string
- Phone string
- Email string
- Website string
- Username string
- Password string
+ FullName string
+ FirmName string
+ Gstin string
+ Phone string
+ Email string
+ Website string
+ Username string
+ Password string
+ LogoFile string
+ SignatureFile string
// will be printed with address on the invoice
- Details string
- IsVerified bool
+ Details string
+ IsVerified bool
// a note is printed on every invoice.
// This is the default that gets automatically set
DefaultInvoiceNote string