From 28a2c991a29951b882723a0f3a4831880b0acb94 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Tue, 4 Aug 2026 20:31:10 -0400 Subject: [PATCH] Bad .gitignore removed all the db.go files. --- .gitignore | 2 +- features/admin/db.go | 174 +++++++++++++++++++++++++ features/auth/db.go | 46 +++++++ features/email/db.go | 9 ++ features/fakepay/db.go | 9 ++ features/paypal/db.go | 9 ++ features/shopping/db.go | 9 ++ features/survey/db.go | 9 ++ tools/cmd/fgen/templates/feature/db.go | 9 ++ 9 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 features/admin/db.go create mode 100644 features/auth/db.go create mode 100644 features/email/db.go create mode 100644 features/fakepay/db.go create mode 100644 features/paypal/db.go create mode 100644 features/shopping/db.go create mode 100644 features/survey/db.go create mode 100644 tools/cmd/fgen/templates/feature/db.go diff --git a/.gitignore b/.gitignore index 70a4b9d..dd824d6 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,4 @@ public webapp bin static/style.css -db.* +db.sqlite3* diff --git a/features/admin/db.go b/features/admin/db.go new file mode 100644 index 0000000..2b3e080 --- /dev/null +++ b/features/admin/db.go @@ -0,0 +1,174 @@ +package features_admin + +import ( + "reflect" + "fmt" + "errors" + "MY/webapp/data" + _ "github.com/mattn/go-sqlite3" + sq "github.com/Masterminds/squirrel" +) + +func Schema(table string) ([]string, error) { + the_type, ok := data.Models()[table] + if !ok { return nil, errors.New("Invalid table") } + + field_num := the_type.NumField() + + fields := make([]string, 0, field_num) + + for i := 0; i < field_num; i++ { + tag := the_type.Field(i).Name + fields = append(fields, tag) + } + + return fields, nil +} + +func SearchTable(search string, table string, limit uint64, page uint64) ([]any, error) { + var results []any + + the_type := data.Models()[table] + like := fmt.Sprint("%", search, "%") + + builder := sq.Select("*"). + Limit(limit). + Offset(limit * page). + From(table) + + field_num := the_type.NumField() + var or_clause sq.Or + + for i := 0; i < field_num; i++ { + tag := the_type.Field(i).Tag.Get("db") + or_clause = append(or_clause, sq.Like{tag: like}) + } + + builder = builder.Where(or_clause) + sql_query, args, err := builder.ToSql() + + if err != nil { return results, err } + + // BUG: refactor this to share a common func with SelectTable + rows, err := data.DB.Queryx(sql_query, args...) + if err != nil { return results, err } + defer rows.Close() + + for rows.Next() { + the_data := reflect.New(the_type).Interface() + err = rows.StructScan(the_data) + if err != nil { return results, err } + + results = append(results, the_data) + } + + return results, rows.Err() +} + +func SelectTable(table string, limit uint64, page uint64) ([]any, error) { + var results []any + the_type := data.Models()[table] + + sql_query, args, err := sq.Select("*"). + Limit(limit). + Offset(limit * page). + From(table). + ToSql() + + if err != nil { return results, err } + + rows, err := data.DB.Queryx(sql_query, args...) + if err != nil { return results, err } + defer rows.Close() + + for rows.Next() { + the_data := reflect.New(the_type).Interface() + err = rows.StructScan(the_data) + if err != nil { return results, err } + + results = append(results, the_data) + } + + return results, rows.Err() +} + +func Get(table string, id int64) (reflect.Value, error) { + the_type := data.Models()[table] + + sql_query, args, err := sq.Select("*").From(table).Where(sq.Eq{"id": id}).ToSql() + if err != nil { return reflect.New(nil), err } + + the_data := reflect.New(the_type) + err = data.DB.Get(the_data.Interface(), sql_query, args...) + + // BUG: not sure if Elem or returning the reflect.New is better + return the_data.Elem(), err +} + +func Delete(table string, id int64) error { + sql_query, args, err := sq.Delete(table).Where(sq.Eq{"id": id}).ToSql() + if err != nil { return err } + + _, err = data.DB.Exec(sql_query, args...) + return err +} + +func Insert(table string, value reflect.Value) (int64, int64, error) { + type_of := value.Type() + field_num := value.NumField() + var columns []string + var values []any + + for i := 0; i < field_num; i++ { + field := value.Field(i) + tag := type_of.Field(i).Tag.Get("db") + if tag == "id" { continue } + columns = append(columns, tag) + values = append(values, field.Interface()) + } + + builder := sq.Insert(table).Columns(columns...).Values(values...) + sql_query, args, err := builder.ToSql() + if err != nil { return -1, -1, err } + + result, err := data.DB.Exec(sql_query, args...) + if err != nil { return -1, -1, err } + + id, err := result.LastInsertId() + if err != nil { return -1, -1, err } + + count, err := result.RowsAffected() + if err != nil { return id, -1, err } + + return id, count, err +} + +func Update(table string, value reflect.Value) (int64, error) { + builder := sq.Update(table) + orig_id := value.FieldByName("Id").Int() + + type_of := value.Type() + field_num := value.NumField() + + for i := 0; i < field_num; i++ { + field := value.Field(i) + tag := type_of.Field(i).Tag.Get("db") + + // skip update of id to avoid replacing it + if tag == "id" { continue } + + builder = builder.Set(tag, field.Interface()) + } + + builder = builder.Where(sq.Eq{"id": orig_id}) + sql_query, args, err := builder.ToSql() + if err != nil { return -1, err } + + fmt.Println("UPDATE QUERY", sql_query, args) + if err != nil { return -1, err} + + _, err = data.DB.Exec(sql_query, args...) + if err != nil { return -1, err } + + return orig_id, err +} diff --git a/features/auth/db.go b/features/auth/db.go new file mode 100644 index 0000000..12190e4 --- /dev/null +++ b/features/auth/db.go @@ -0,0 +1,46 @@ +package features_auth + +import ( + "golang.org/x/crypto/bcrypt" + + "github.com/gofiber/fiber/v2" + _ "github.com/mattn/go-sqlite3" + sq "github.com/Masterminds/squirrel" + + "MY/webapp/data" + "MY/webapp/common" +) + +func SetUserPassword(user *data.User) error { + hashed, err := bcrypt.GenerateFromPassword([]byte(user.Password), 12) + if err != nil { return err } + + user.Password = string(hashed) + return nil +} + +func LogoutUser(c *fiber.Ctx) error { + sess, err := common.STORE.Get(c) + if err != nil { return err } + + err = sess.Destroy() + if err != nil { return err } + + err = sess.Save() + return err +} + +func LoginUser(result *data.User, login *data.Login) (bool, error) { + sql, args, err := sq.Select("username, password"). + From("user").Where("username=?", login.Username).ToSql() + + if err != nil { return false, err } + + err = data.DB.Get(result, sql, args...) + if err != nil { return false, err } + + pass_good := bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(login.Password)) + if pass_good != nil { return false, pass_good } + + return login.Username == result.Username && pass_good == nil, nil +} diff --git a/features/email/db.go b/features/email/db.go new file mode 100644 index 0000000..15da825 --- /dev/null +++ b/features/email/db.go @@ -0,0 +1,9 @@ +package features_email + +import ( +// "MY/webapp/data" +// _ "github.com/mattn/go-sqlite3" +// sq "github.com/Masterminds/squirrel" +) + + diff --git a/features/fakepay/db.go b/features/fakepay/db.go new file mode 100644 index 0000000..3b488aa --- /dev/null +++ b/features/fakepay/db.go @@ -0,0 +1,9 @@ +package features_fakepay + +import ( +// "MY/webapp/data" +// _ "github.com/mattn/go-sqlite3" +// sq "github.com/Masterminds/squirrel" +) + + diff --git a/features/paypal/db.go b/features/paypal/db.go new file mode 100644 index 0000000..abcf93a --- /dev/null +++ b/features/paypal/db.go @@ -0,0 +1,9 @@ +package features_paypal + +import ( +// "MY/webapp/data" +// _ "github.com/mattn/go-sqlite3" +// sq "github.com/Masterminds/squirrel" +) + + diff --git a/features/shopping/db.go b/features/shopping/db.go new file mode 100644 index 0000000..dc88ed5 --- /dev/null +++ b/features/shopping/db.go @@ -0,0 +1,9 @@ +package features_shopping + +import ( +// "MY/webapp/data" +// _ "github.com/mattn/go-sqlite3" +// sq "github.com/Masterminds/squirrel" +) + + diff --git a/features/survey/db.go b/features/survey/db.go new file mode 100644 index 0000000..9f5a74b --- /dev/null +++ b/features/survey/db.go @@ -0,0 +1,9 @@ +package features_survey + +import ( +// "MY/webapp/data" +// _ "github.com/mattn/go-sqlite3" +// sq "github.com/Masterminds/squirrel" +) + + diff --git a/tools/cmd/fgen/templates/feature/db.go b/tools/cmd/fgen/templates/feature/db.go new file mode 100644 index 0000000..15c9f29 --- /dev/null +++ b/tools/cmd/fgen/templates/feature/db.go @@ -0,0 +1,9 @@ +package features_{{ .Name }} + +import ( +// "MY/webapp/data" +// _ "github.com/mattn/go-sqlite3" +// sq "github.com/Masterminds/squirrel" +) + +