aboutsummaryrefslogtreecommitdiff
path: root/repository
diff options
context:
space:
mode:
Diffstat (limited to 'repository')
-rw-r--r--repository/node.go58
-rw-r--r--repository/post.go70
-rw-r--r--repository/topic.go101
-rw-r--r--repository/user.go98
4 files changed, 249 insertions, 78 deletions
diff --git a/repository/node.go b/repository/node.go
deleted file mode 100644
index 27282af..0000000
--- a/repository/node.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package repository
-
-import (
- "context"
-
- "github.com/uptrace/bun"
- "gitrepo.ru/neonxp/gorum/models"
-)
-
-type Node struct {
- db *bun.DB
-}
-
-func NewNode(db *bun.DB) *Node {
- return &Node{
- db: db,
- }
-}
-
-func (t *Node) Create(
- ctx context.Context,
- ntype models.NodeType,
- text string,
- authorID int,
- parentID int,
-) (int, error) {
- post := &models.Node{
- Type: ntype,
- Text: text,
- AuthorID: authorID,
- ParentID: parentID,
- }
- _, err := t.db.NewInsert().Model(post).Returning("id").Exec(ctx)
-
- return post.ID, err
-}
-
-func (t *Node) Get(ctx context.Context, topicID int) (*models.Node, error) {
- node := new(models.Node)
-
- return node, t.db.NewSelect().
- Model(node).
- Where(`n.id = ?`, topicID).
- Relation("Author").
- Relation("Parent").
- Scan(ctx)
-}
-
-func (t *Node) List(ctx context.Context, topicID int) ([]*models.Node, error) {
- posts := make([]*models.Node, 0)
-
- return posts, t.db.NewSelect().
- Model(&posts).
- Where(`parent_id = ?`, topicID).
- Relation("Author").
- Relation("Children").
- Scan(ctx)
-}
diff --git a/repository/post.go b/repository/post.go
new file mode 100644
index 0000000..1b0fef6
--- /dev/null
+++ b/repository/post.go
@@ -0,0 +1,70 @@
+package repository
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+ "time"
+
+ "gitrepo.ru/neonxp/gorum/models"
+ "go.etcd.io/bbolt"
+)
+
+type Post struct {
+ db *bbolt.DB
+}
+
+func NewPost(db *bbolt.DB) *Post {
+ return &Post{
+ db: db,
+ }
+}
+
+func (t *Post) CreatePost(
+ text string,
+ authorID string,
+ topicID uint64,
+) (uint64, error) {
+ post := &models.Post{
+ Text: text,
+ AuthorID: authorID,
+ CreatedAt: time.Now(),
+ UpdatedAt: time.Now(),
+ }
+
+ return post.ID, t.db.Update(func(tx *bbolt.Tx) error {
+ bucket, err := tx.CreateBucketIfNotExists([]byte(fmt.Sprintf("posts_%d", topicID)))
+ if err != nil {
+ return err
+ }
+ id, err := bucket.NextSequence()
+ if err != nil {
+ return err
+ }
+ post.ID = id
+ pb, err := json.Marshal(post)
+ if err != nil {
+ return err
+ }
+
+ return bucket.Put([]byte(strconv.Itoa(int(id))), pb)
+ })
+}
+
+func (t *Post) List(topicID uint64) ([]*models.Post, error) {
+ posts := make([]*models.Post, 0)
+
+ return posts, t.db.View(func(tx *bbolt.Tx) error {
+ return tx.Bucket([]byte(fmt.Sprintf("posts_%d", topicID))).ForEach(func(k, v []byte) error {
+ post := new(models.Post)
+
+ if err := json.Unmarshal(v, post); err != nil {
+ return err
+ }
+
+ posts = append(posts, post)
+
+ return nil
+ })
+ })
+}
diff --git a/repository/topic.go b/repository/topic.go
new file mode 100644
index 0000000..4c34643
--- /dev/null
+++ b/repository/topic.go
@@ -0,0 +1,101 @@
+package repository
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+ "time"
+
+ "gitrepo.ru/neonxp/gorum/models"
+ "go.etcd.io/bbolt"
+)
+
+type Topic struct {
+ db *bbolt.DB
+}
+
+func NewTopic(db *bbolt.DB) *Topic {
+ return &Topic{
+ db: db,
+ }
+}
+
+func (t *Topic) Init() error {
+ return t.db.Update(func(tx *bbolt.Tx) error {
+ _, err := tx.CreateBucketIfNotExists([]byte("topics"))
+ return err
+ })
+}
+
+func (t *Topic) Create(title, text, authorID string, parentID uint64) (*models.Topic, error) {
+ topic := &models.Topic{
+ Topic: title,
+ Text: text,
+ AuthorID: authorID,
+ ParentID: parentID,
+ CreatedAt: time.Now(),
+ UpdatedAt: time.Now(),
+ }
+
+ return topic, t.db.Update(func(tx *bbolt.Tx) error {
+ bucket, err := tx.CreateBucketIfNotExists([]byte("topics"))
+ if err != nil {
+ return err
+ }
+ id, err := bucket.NextSequence()
+ if err != nil {
+ return err
+ }
+ topic.ID = id
+ tb, err := json.Marshal(topic)
+ if err != nil {
+ return err
+ }
+
+ if _, err := tx.CreateBucketIfNotExists([]byte(fmt.Sprintf("posts_%d", topic.ID))); err != nil {
+ return err
+ }
+
+ return bucket.Put([]byte(strconv.Itoa(int(topic.ID))), tb)
+ })
+}
+
+func (t *Topic) List(parentID uint64) ([]*models.Topic, error) {
+ topics := make([]*models.Topic, 0)
+
+ return topics, t.db.View(func(tx *bbolt.Tx) error {
+ bucket := tx.Bucket([]byte("topics"))
+ if bucket == nil {
+ return models.ErrDBNotInitialized
+ }
+
+ return bucket.ForEach(func(k, v []byte) error {
+ t := new(models.Topic)
+ if err := json.Unmarshal(v, t); err != nil {
+ return err
+ }
+ if t.ParentID == parentID {
+ topics = append(topics, t)
+ }
+
+ return nil
+ })
+ })
+}
+
+func (t *Topic) Get(topicID uint64) (*models.Topic, error) {
+ topic := new(models.Topic)
+
+ return topic, t.db.View(func(tx *bbolt.Tx) error {
+ bucket := tx.Bucket([]byte("topics"))
+ if bucket == nil {
+ return models.ErrDBNotInitialized
+ }
+ tb := bucket.Get([]byte(strconv.Itoa(int(topicID))))
+ if tb == nil {
+ return models.ErrTopicNotFound
+ }
+
+ return json.Unmarshal(tb, topic)
+ })
+}
diff --git a/repository/user.go b/repository/user.go
index 5c3cce6..b01eaee 100644
--- a/repository/user.go
+++ b/repository/user.go
@@ -1,31 +1,44 @@
package repository
import (
- "context"
+ "encoding/json"
"fmt"
- "github.com/uptrace/bun"
+ normalizer "github.com/dimuska139/go-email-normalizer/v2"
"gitrepo.ru/neonxp/gorum/models"
+ "go.etcd.io/bbolt"
"golang.org/x/crypto/bcrypt"
)
type User struct {
- db *bun.DB
+ db *bbolt.DB
}
-func NewUser(db *bun.DB) *User {
+func NewUser(db *bbolt.DB) *User {
return &User{
db: db,
}
}
-func (u *User) Create(ctx context.Context, email, password, username string, role models.UserRole) (int, error) {
+func (t *User) Init() error {
+ return t.db.Update(func(tx *bbolt.Tx) error {
+ _, err := tx.CreateBucketIfNotExists([]byte("users"))
+ return err
+ })
+}
+func (u *User) Create(email, password, username string, role models.UserRole) error {
+
+ if len(password) < 8 {
+ return models.ErrInvalidPassword
+ }
hpassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
- return 0, models.ErrInvalidPassword
+ return models.ErrInvalidPassword
}
+ email = normalizer.NewNormalizer().Normalize(email)
+
user := &models.User{
Email: email,
Password: string(hpassword),
@@ -33,29 +46,74 @@ func (u *User) Create(ctx context.Context, email, password, username string, rol
Role: role,
}
- if _, err := u.db.NewInsert().Model(user).Returning("id").Exec(ctx); err != nil {
- return 0, models.ErrUserAlreadyExists
- }
+ u.db.Update(func(tx *bbolt.Tx) error {
+ bucket, err := tx.CreateBucketIfNotExists([]byte("users"))
+ if err != nil {
+ return err
+ }
+ ub := bucket.Get([]byte(email))
+ if ub != nil {
+ return models.ErrUserAlreadyExists
+ }
+
+ ub, err = json.Marshal(user)
+ if err != nil {
+ return err
+ }
+
+ return bucket.Put([]byte(email), ub)
+ })
- return user.ID, nil
+ return nil
}
-func (u *User) Login(ctx context.Context, email, password string) (*models.User, error) {
+func (u *User) Login(email, password string) (*models.User, error) {
user := new(models.User)
+ email = normalizer.NewNormalizer().Normalize(email)
- if err := u.db.NewSelect().Model(user).Where("email = ?", email).Scan(ctx); err != nil {
- return nil, fmt.Errorf("user not found: %w", models.ErrInvalidUserOrPassword)
- }
+ return user, u.db.View(func(tx *bbolt.Tx) error {
+ ub := tx.Bucket([]byte("users")).Get([]byte(email))
+ if ub == nil {
+ return models.ErrInvalidUserOrPassword
+ }
+ if err := json.Unmarshal(ub, user); err != nil {
+ return err
+ }
- if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
- return nil, fmt.Errorf("invalid password: %w", models.ErrInvalidUserOrPassword)
- }
+ if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
+ return fmt.Errorf("invalid password: %w", models.ErrInvalidUserOrPassword)
+ }
+
+ return nil
+ })
+}
+
+func (u *User) Get(email string) (*models.User, error) {
+ user := new(models.User)
+ email = normalizer.NewNormalizer().Normalize(email)
+
+ return user, u.db.View(func(tx *bbolt.Tx) error {
+ ub := tx.Bucket([]byte("users")).Get([]byte(email))
+ if ub == nil {
+ return models.ErrInvalidUserOrPassword
+ }
- return user, nil
+ return json.Unmarshal(ub, user)
+ })
}
-func (u *User) List(ctx context.Context) ([]*models.User, error) {
+func (u *User) List() ([]*models.User, error) {
ret := make([]*models.User, 0)
- return ret, u.db.NewSelect().Model(&ret).Scan(ctx)
+ return ret, u.db.View(func(tx *bbolt.Tx) error {
+ bucket := tx.Bucket([]byte("users"))
+ return bucket.ForEach(func(k, v []byte) error {
+ u := new(models.User)
+ if err := json.Unmarshal(v, u); err != nil {
+ return err
+ }
+ ret = append(ret, u)
+ return nil
+ })
+ })
}