Refactoring, added generic Store
This commit is contained in:
90
storage/mongoStore.go
Normal file
90
storage/mongoStore.go
Normal file
@ -0,0 +1,90 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
func NewStore[T any](db *MongodbStorage, collection string) Store[T] {
|
||||
return Store[T]{
|
||||
Db: db.Db,
|
||||
Coll: db.Collection(collection),
|
||||
}
|
||||
}
|
||||
|
||||
type Store[T any] struct {
|
||||
Db *mongo.Client
|
||||
Coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (s Store[T]) InsertOne(ctx context.Context, item *T) (primitive.ObjectID, error) {
|
||||
result, err := s.Coll.InsertOne(ctx, item)
|
||||
if err != nil {
|
||||
if e, ok := err.(mongo.WriteError); ok {
|
||||
log.Printf("Error writing new item of type %v: %v ", reflect.TypeOf(item), e)
|
||||
return primitive.NilObjectID, e
|
||||
}
|
||||
log.Printf("Error creating new item of type %v: %v ", reflect.TypeOf(item), err)
|
||||
return primitive.NilObjectID, err
|
||||
}
|
||||
rid, _ := result.InsertedID.(primitive.ObjectID)
|
||||
return rid, nil
|
||||
}
|
||||
|
||||
func (s Store[T]) GetById(ctx context.Context, id primitive.ObjectID) (*T, error) {
|
||||
res := s.Coll.FindOne(ctx, bson.D{{Key: "_id", Value: id}})
|
||||
if res.Err() != nil {
|
||||
return nil, res.Err()
|
||||
}
|
||||
var item T
|
||||
res.Decode(&item)
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (s Store[T]) GetOne(ctx context.Context, filter *bson.D) (*T, error) {
|
||||
f := getFilter(filter)
|
||||
res := s.Coll.FindOne(ctx, f)
|
||||
if res.Err() != nil {
|
||||
return nil, res.Err()
|
||||
}
|
||||
var item T
|
||||
res.Decode(&item)
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (s Store[T]) GetMany(ctx context.Context, filter *bson.D) ([]*T, error) {
|
||||
f := getFilter(filter)
|
||||
cur, err := s.Coll.Find(ctx, f)
|
||||
if err != nil {
|
||||
log.Println("Error fetching items: ", err)
|
||||
return nil, err
|
||||
}
|
||||
var res []*T
|
||||
err = cur.All(ctx, &res)
|
||||
if err != nil {
|
||||
log.Println("Error collecting items to slice: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
func (s Store[T]) DeleteByID(ctx context.Context, id primitive.ObjectID) error {
|
||||
_, err := s.Coll.DeleteOne(ctx, bson.D{{Key: "_id", Value: id}})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s Store[T]) ReplaceByID(ctx context.Context, id primitive.ObjectID, item *T) error {
|
||||
_, err := s.Coll.ReplaceOne(ctx, bson.D{{Key: "_id", Value: id}}, item)
|
||||
return err
|
||||
}
|
||||
|
||||
func getFilter(f *bson.D) bson.D {
|
||||
if f == nil {
|
||||
return bson.D{}
|
||||
}
|
||||
return *f
|
||||
}
|
110
storage/mongostorage.go
Normal file
110
storage/mongostorage.go
Normal file
@ -0,0 +1,110 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
type MongodbStorage struct {
|
||||
Db *mongo.Client
|
||||
}
|
||||
|
||||
func (m MongodbStorage) CreateUser(user *User) (primitive.ObjectID, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[User](&m, "users")
|
||||
return store.InsertOne(ctx, user)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetUserByID(id primitive.ObjectID) (*User, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[User](&m, "users")
|
||||
return store.GetById(ctx, id)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetUser(filter *bson.D) (*User, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[User](&m, "users")
|
||||
return store.GetOne(ctx, filter)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetUsers(filter *bson.D) ([]*User, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[User](&m, "users")
|
||||
return store.GetMany(ctx, filter)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) UpdateUser(user *User) error {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[User](&m, "users")
|
||||
return store.ReplaceByID(ctx, user.Id, user)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) DeleteUser(id primitive.ObjectID) error {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[User](&m, "users")
|
||||
return store.DeleteByID(ctx, id)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) CreateSession(s *Session) (primitive.ObjectID, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Session](&m, "sessions")
|
||||
return store.InsertOne(ctx, s)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetSessionByToken(token string) (*Session, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Session](&m, "sessions")
|
||||
return store.GetOne(ctx, &bson.D{{Key: "token", Value: token}})
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetUserSessions(user *User) ([]*Session, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Session](&m, "sessions")
|
||||
return store.GetMany(ctx, &bson.D{{Key: "userid", Value: user.Id}})
|
||||
}
|
||||
|
||||
func (m MongodbStorage) DeleteSession(id primitive.ObjectID) error {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Session](&m, "sessions")
|
||||
return store.DeleteByID(ctx, id)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) CreateBookmark(bookmark *Bookmark) (primitive.ObjectID, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Bookmark](&m, "bookmarks")
|
||||
return store.InsertOne(ctx, bookmark)
|
||||
|
||||
}
|
||||
func (m MongodbStorage) GetBookmarkByID(id primitive.ObjectID) (*Bookmark, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Bookmark](&m, "bookmarks")
|
||||
return store.GetById(ctx, id)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetBookmark(filter *bson.D) (*Bookmark, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Bookmark](&m, "bookmarks")
|
||||
return store.GetOne(ctx, filter)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetBookmarks(filter *bson.D) ([]*Bookmark, error) {
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Bookmark](&m, "bookmarks")
|
||||
return store.GetMany(ctx, filter)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) GetUserBookmarks(user *User, filter *bson.D) ([]*Bookmark, error) {
|
||||
passedFilter := getFilter(filter)
|
||||
f := bson.D{{Key: "userid", Value: user.Id}}
|
||||
f = append(f, passedFilter...)
|
||||
ctx := context.TODO()
|
||||
store := NewStore[Bookmark](&m, "bookmarks")
|
||||
return store.GetMany(ctx, &f)
|
||||
}
|
||||
|
||||
func (m MongodbStorage) Collection(col string) *mongo.Collection {
|
||||
return m.Db.Database("nash").Collection(col)
|
||||
}
|
29
storage/storage.go
Normal file
29
storage/storage.go
Normal file
@ -0,0 +1,29 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
// Users
|
||||
CreateUser(*User) (primitive.ObjectID, error)
|
||||
GetUser(*bson.D) (*User, error)
|
||||
GetUsers(*bson.D) ([]*User, error)
|
||||
GetUserByID(primitive.ObjectID) (*User, error)
|
||||
UpdateUser(*User) error
|
||||
DeleteUser(primitive.ObjectID) error
|
||||
|
||||
// Sessions
|
||||
CreateSession(*Session) (primitive.ObjectID, error)
|
||||
GetSessionByToken(string) (*Session, error)
|
||||
GetUserSessions(*User) ([]*Session, error)
|
||||
DeleteSession(primitive.ObjectID) error
|
||||
|
||||
// Bookmarks
|
||||
CreateBookmark(*Bookmark) (primitive.ObjectID, error)
|
||||
GetBookmarkByID(primitive.ObjectID) (*Bookmark, error)
|
||||
GetBookmark(*bson.D) (*Bookmark, error)
|
||||
GetBookmarks(*bson.D) ([]*Bookmark, error)
|
||||
GetUserBookmarks(*User, *bson.D) ([]*Bookmark, error)
|
||||
}
|
67
storage/types.go
Normal file
67
storage/types.go
Normal file
@ -0,0 +1,67 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Id primitive.ObjectID `bson:"_id" json:"id,omitempty"`
|
||||
Username string
|
||||
Password []byte `json:"-"`
|
||||
IsAdmin bool
|
||||
LastLogin time.Time
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
Id primitive.ObjectID `bson:"_id" json:"id,omitempty"`
|
||||
Token string `json:"-"`
|
||||
UserID primitive.ObjectID
|
||||
IP string
|
||||
LoggedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
IsAdmin bool
|
||||
}
|
||||
|
||||
type ApiKey struct {
|
||||
Id primitive.ObjectID `bson:"_id" json:"id,omitempty"`
|
||||
UserID primitive.ObjectID
|
||||
Key string
|
||||
}
|
||||
|
||||
type Folder struct {
|
||||
Id primitive.ObjectID `bson:"_id" json:"id,omitempty"`
|
||||
Name string
|
||||
ParentID primitive.ObjectID
|
||||
Icon []byte
|
||||
}
|
||||
|
||||
type Bookmark struct {
|
||||
Id primitive.ObjectID `bson:"_id" json:"id,omitempty"`
|
||||
Name string
|
||||
Url string
|
||||
UserID primitive.ObjectID
|
||||
FolderID primitive.ObjectID
|
||||
Tags []string
|
||||
// Icon []byte
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
type Note struct {
|
||||
Id primitive.ObjectID `bson:"_id" json:"id,omitempty"`
|
||||
Name string
|
||||
Tags []string
|
||||
Content string
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
func GenSessionToken() string {
|
||||
b := make([]byte, 128)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return ""
|
||||
}
|
||||
return hex.EncodeToString(b)
|
||||
}
|
Reference in New Issue
Block a user