aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/user
diff options
context:
space:
mode:
authorVidhu Kant Sharma <vidhukant@vidhukant.com>2025-10-12 00:05:30 +0530
committerVidhu Kant Sharma <vidhukant@vidhukant.com>2025-10-12 00:05:30 +0530
commita356803594ab36fa69e7dbcbd79261d8b46f4262 (patch)
tree0146efe4c52b1c65c1967ab1f412306c410c10d4 /user
parent193be465b21838d2796fafbe1c5d9854038a3f8c (diff)
removed useless user fields and functions, added rolesv0.19.0
Diffstat (limited to 'user')
-rw-r--r--user/controller.go116
-rw-r--r--user/router.go2
-rw-r--r--user/service.go35
-rw-r--r--user/user.go55
-rw-r--r--user/validators.go60
5 files changed, 62 insertions, 206 deletions
diff --git a/user/controller.go b/user/controller.go
index 1dc85da..7dd519a 100644
--- a/user/controller.go
+++ b/user/controller.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2025 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
@@ -20,8 +20,6 @@ package user
import (
e "vidhukant.com/openbills/errors"
"github.com/gin-gonic/gin"
- "github.com/google/uuid"
- "github.com/spf13/viper"
"net/http"
)
@@ -37,7 +35,7 @@ func handleGetUser (ctx *gin.Context) {
userId := uId.(uint)
- err := GetUser(&user, userId)
+ err := GetUserById(&user, userId)
if err != nil {
ctx.Error(err)
ctx.Abort()
@@ -48,116 +46,6 @@ func handleGetUser (ctx *gin.Context) {
user.Password = ""
ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
"data": user,
})
}
-
-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
-
- var user User
- user.ID = id
-
- // TODO: add a verification mechanism
- err := user.del()
- if err != nil {
- ctx.Error(err)
- ctx.Abort()
- return
- }
-
- ctx.JSON(http.StatusOK, gin.H{
- "message": "success",
- })
-}
diff --git a/user/router.go b/user/router.go
index d9fa7e0..eb7270a 100644
--- a/user/router.go
+++ b/user/router.go
@@ -25,7 +25,5 @@ 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 222df4a..4dec8bc 100644
--- a/user/service.go
+++ b/user/service.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2025 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
@@ -27,14 +27,12 @@ func (u *User) Create() error {
return res.Error
}
-func GetUserWithAccountName(user *User, accountName, method string) error {
+func GetUserByAccountName(user *User, accountName, method string) error {
if method != "username" && method != "email" {
return e.ErrInvalidLoginMethod
}
- res := db.Where(method + " = ?", accountName).Find(&user)
-
- // TODO: handle potential errors
+ res := db.Where(method + " = ?", accountName).Preload("Roles").Find(&user)
if res.Error != nil {
return res.Error
}
@@ -46,10 +44,8 @@ func GetUserWithAccountName(user *User, accountName, method string) error {
return nil
}
-func GetUser(user *User, id uint) error {
- res := db.Find(&user, id)
-
- // TODO: handle potential errors
+func GetUserById(user *User, id uint) error {
+ res := db.Preload("Roles").Find(&user, id)
if res.Error != nil {
return res.Error
}
@@ -63,8 +59,6 @@ func GetUser(user *User, id uint) error {
func (u *User) del() error {
res := db.Delete(u)
-
- // TODO: handle potential errors
if res.Error != nil {
return res.Error
}
@@ -76,21 +70,4 @@ 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
-}
+// TODO: email/password updation (no username changes) with OTP verification or something
diff --git a/user/user.go b/user/user.go
index dbcbad0..4d0ffcb 100644
--- a/user/user.go
+++ b/user/user.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2025 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
@@ -20,7 +20,6 @@ package user
import (
d "vidhukant.com/openbills/db"
e "vidhukant.com/openbills/errors"
- u "vidhukant.com/openbills/util"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
"github.com/spf13/viper"
@@ -32,35 +31,45 @@ var db *gorm.DB
func init() {
db = d.DB
- db.AutoMigrate(&User{})
+ db.AutoMigrate(&User{}, &Role{})
COST = viper.GetInt("cryptography.password_hashing_cost")
}
+var VALID_ROLES []string = []string {
+ "customer.*", "customer.read", "customer.write", "customer.delete",
+ "item.*", "item.read", "item.write", "item.delete",
+ "invoice.*", "invoice.read", "invoice.write", "invoice.delete",
+ "admin", "*.*",
+}
+
+type Role struct {
+ ID uint
+ UserID uint
+ Name string
+}
+
type User struct {
- gorm.Model
- u.Address
- TokenVersion uint // this can be incremented to disable existing refresh token(s)
- FullName string
- FirmName string
- Gstin string
- Phone string
- Email string
- Website string
- Username string
- Password string
- LogoFile string
- SignatureFile string
- IsVerified bool // this should be removed and tokens should be issued upon verification
- // will be printed with address on the invoice
- Details string
- // a note is printed on every invoice.
- // This is the default that gets automatically set
- DefaultInvoiceNote string
+ ID uint
+ TokenVersion uint // this can be incremented to disable existing refresh token(s)
+ Username string
+ Email string
+ Password string
+ Roles []Role `gorm:"constraint:OnDelete:CASCADE;"`
+}
+
+func RolesToStringList(roles []Role) []string {
+ x := []string{}
+
+ for _, i := range roles {
+ x = append(x, i.Name)
+ }
+
+ return x
}
func CheckPassword(user *User, accountName, method, pass string) error {
- err := GetUserWithAccountName(user, accountName, method)
+ err := GetUserByAccountName(user, accountName, method)
if err != nil {
return err
}
diff --git a/user/validators.go b/user/validators.go
index e497122..e9a894c 100644
--- a/user/validators.go
+++ b/user/validators.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2025 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
@@ -40,45 +40,40 @@ func validatePassword(pass string) error {
func validateUsername(username string) error {
// check if username is too short
- if len(username) < viper.GetInt("username.min_username_length") {
+ if len(username) < 2 {
return errors.ErrUsernameTooShort
}
// check if username is too long
- if len(username) > viper.GetInt("username.max_username_length") {
+ if len(username) > 32 {
return errors.ErrUsernameTooLong
}
-
- for _, char := range username {
- if !strings.Contains(username, string(char)) {
- return errors.ErrInvalidUsername
- }
- }
+
+ // (11th October 2025) what the fuck even is this
+ // I'm not even deleting this I can't stop laughing
+ //
+ // for _, char := range username {
+ // if !strings.Contains(username, string(char)) {
+ // return errors.ErrInvalidUsername
+ // }
+ // }
return nil
}
func (u *User) validate() error {
- u.Username = strings.TrimSpace(u.Username)
u.Email = strings.TrimSpace(u.Email)
- u.Phone = strings.TrimSpace(u.Phone)
- u.Website = strings.TrimSpace(u.Website)
- u.Gstin = strings.TrimSpace(u.Gstin)
- u.IsVerified = false
-
- // don't validate if GSTIN is empty
- if u.Gstin != "" && !util.ValidateGstin(u.Gstin) {
- return errors.ErrInvalidGSTIN
- }
-
- // don't validate if phone is empty
- if u.Phone != "" && !util.ValidatePhone(u.Phone) {
- return errors.ErrInvalidPhone
- }
+ u.Username = strings.TrimSpace(u.Username)
- // don't validate if website is empty
- if u.Website != "" && !util.ValidateWebsite(u.Website) {
- return errors.ErrInvalidWebsite
+ // don't accept empty username
+ if u.Username == "" {
+ return errors.ErrEmptyUsername
+ } else {
+ // validate username
+ err := validateUsername(u.Username)
+ if err != nil {
+ return err
+ }
}
// don't accept empty email
@@ -91,17 +86,6 @@ func (u *User) validate() error {
}
}
- // don't accept empty username
- if u.Username == "" {
- return errors.ErrEmptyUsername
- } else {
- // validate username
- err := validateUsername(u.Username)
- if err != nil {
- return err
- }
- }
-
// validate password
err := validatePassword(u.Password)
if err != nil {