github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/plugin/basic/mongodb_repository.go (about) 1 package basic 2 3 import ( 4 "context" 5 "github.com/hellofresh/janus/pkg/plugin/basic/encrypt" 6 "time" 7 8 log "github.com/sirupsen/logrus" 9 "go.mongodb.org/mongo-driver/bson" 10 "go.mongodb.org/mongo-driver/mongo" 11 "go.mongodb.org/mongo-driver/mongo/options" 12 ) 13 14 const ( 15 collectionName string = "basic_auth" 16 17 mongoQueryTimeout = 10 * time.Second 18 ) 19 20 // User represents an user 21 type User struct { 22 Username string `json:"username"` 23 Password string `json:"password"` 24 } 25 26 // Repository represents an user repository 27 type Repository interface { 28 FindAll() ([]*User, error) 29 FindByUsername(username string) (*User, error) 30 Add(user *User) error 31 Remove(username string) error 32 } 33 34 // MongoRepository represents a mongodb repository 35 type MongoRepository struct { 36 collection *mongo.Collection 37 hash encrypt.Hash 38 } 39 40 // NewMongoRepository creates a mongo API definition repo 41 func NewMongoRepository(db *mongo.Database) (*MongoRepository, error) { 42 return &MongoRepository{collection: db.Collection(collectionName), hash: encrypt.Hash{}}, nil 43 } 44 45 // FindAll fetches all the API definitions available 46 func (r *MongoRepository) FindAll() ([]*User, error) { 47 var result []*User 48 49 ctx, cancel := context.WithTimeout(context.Background(), mongoQueryTimeout) 50 defer cancel() 51 52 cur, err := r.collection.Find(ctx, bson.M{}, options.Find().SetSort(bson.D{{Key: "username", Value: 1}})) 53 if err != nil { 54 return nil, err 55 } 56 defer cur.Close(ctx) 57 58 for cur.Next(ctx) { 59 u := new(User) 60 if err := cur.Decode(u); err != nil { 61 return nil, err 62 } 63 64 result = append(result, u) 65 } 66 67 return result, cur.Err() 68 } 69 70 // FindByUsername find an user by username 71 func (r *MongoRepository) FindByUsername(username string) (*User, error) { 72 return r.findOneByQuery(bson.M{"username": username}) 73 } 74 75 func (r *MongoRepository) findOneByQuery(query interface{}) (*User, error) { 76 var result User 77 78 ctx, cancel := context.WithTimeout(context.Background(), mongoQueryTimeout) 79 defer cancel() 80 81 err := r.collection.FindOne(ctx, query).Decode(&result) 82 if err == mongo.ErrNoDocuments { 83 return nil, ErrUserNotFound 84 } 85 86 return &result, err 87 } 88 89 // Add adds an user to the repository 90 func (r *MongoRepository) Add(user *User) error { 91 ctx, cancel := context.WithTimeout(context.Background(), mongoQueryTimeout) 92 defer cancel() 93 94 hash, err := r.hash.Generate(user.Password) 95 if err != nil { 96 log.Errorf("error hashing password: %v", err) 97 return err 98 } 99 100 user.Password = hash 101 102 if err := r.collection.FindOneAndUpdate( 103 ctx, 104 bson.M{"username": user.Username}, 105 bson.M{"$set": user}, 106 options.FindOneAndUpdate().SetUpsert(true), 107 ).Err(); err != nil { 108 log.WithField("username", user.Username).Error("There was an error adding the user") 109 return err 110 } 111 112 log.WithField("username", user.Username).Debug("User added") 113 return nil 114 } 115 116 // Remove an user from the repository 117 func (r *MongoRepository) Remove(username string) error { 118 ctx, cancel := context.WithTimeout(context.Background(), mongoQueryTimeout) 119 defer cancel() 120 121 res, err := r.collection.DeleteOne(ctx, bson.M{"username": username}) 122 if err != nil { 123 log.WithField("username", username).Error("There was an error removing the user") 124 return err 125 } 126 127 if res.DeletedCount < 1 { 128 return ErrUserNotFound 129 } 130 131 log.WithField("username", username).Debug("User removed") 132 return nil 133 }