diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | conf/conf.go | 6 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | go.sum | 3 | ||||
| -rw-r--r-- | main.go | 7 | ||||
| -rw-r--r-- | openbills.toml | 3 | ||||
| -rw-r--r-- | user/controller.go | 92 | ||||
| -rw-r--r-- | user/router.go | 4 | ||||
| -rw-r--r-- | user/service.go | 21 | ||||
| -rw-r--r-- | user/user.go | 22 | 
10 files changed, 143 insertions, 18 deletions
@@ -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())  } @@ -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 @@ -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= @@ -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  |