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  }