package rbac import ( "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/database" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors" "code.fbi.h-da.de/danet/gosdn/controller/store" "github.com/google/uuid" log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // DatabaseUserStore is used to store users in database type DatabaseUserStore struct { userStoreName string } // Add adds an User. func (s *DatabaseUserStore) Add(userToAdd rbac.User) error { client, ctx, cancel := database.GetMongoConnection() defer cancel() defer client.Disconnect(ctx) _, err := client.Database(database.DatabaseName). Collection(s.userStoreName). InsertOne(ctx, userToAdd) if err != nil { if mongo.IsDuplicateKeyError(err) { return nil } return errors.ErrCouldNotCreate{StoreName: s.userStoreName} } return nil } // Delete deletes an User. func (s *DatabaseUserStore) Delete(userToDelete rbac.User) error { client, ctx, cancel := database.GetMongoConnection() defer cancel() defer client.Disconnect(ctx) _, err := client.Database(database.DatabaseName). Collection(s.userStoreName). DeleteOne(ctx, bson.D{primitive.E{Key: "_id", Value: userToDelete.ID().String()}}) if err != nil { return errors.ErrCouldNotFind{ID: userToDelete.ID(), Name: userToDelete.Name()} } return nil } // Get takes a User's UUID or name and returns the User. If the requested // User does not exist an error is returned. func (s *DatabaseUserStore) Get(query store.Query) (rbac.LoadedUser, error) { var loadedUser rbac.LoadedUser if query.ID != uuid.Nil { loadedUser, err := s.getByID(query.ID) if err != nil { return loadedUser, err } return loadedUser, nil } loadedUser, err := s.getByName(query.Name) if err != nil { return loadedUser, err } return loadedUser, nil } func (s *DatabaseUserStore) getByID(idOfUser uuid.UUID) (rbac.LoadedUser, error) { var loadedUser rbac.LoadedUser client, ctx, cancel := database.GetMongoConnection() defer cancel() defer client.Disconnect(ctx) db := client.Database(database.DatabaseName) collection := db.Collection(s.userStoreName) result := collection.FindOne(ctx, bson.D{primitive.E{Key: "_id", Value: idOfUser.String()}}) if result == nil { return loadedUser, errors.ErrCouldNotFind{ID: idOfUser} } err := result.Decode(&loadedUser) if err != nil { log.Printf("Failed marshalling %v", err) return loadedUser, errors.ErrCouldNotMarshall{StoreName: s.userStoreName} } return loadedUser, nil } func (s *DatabaseUserStore) getByName(nameOfUser string) (rbac.LoadedUser, error) { var loadedUser rbac.LoadedUser client, ctx, cancel := database.GetMongoConnection() defer cancel() defer client.Disconnect(ctx) db := client.Database(database.DatabaseName) collection := db.Collection(s.userStoreName) result := collection.FindOne(ctx, bson.D{primitive.E{Key: "username", Value: nameOfUser}}) if result == nil { return loadedUser, errors.ErrCouldNotFind{Name: nameOfUser} } err := result.Decode(&loadedUser) if err != nil { log.Printf("Failed marshalling %v", err) return loadedUser, errors.ErrCouldNotMarshall{StoreName: s.userStoreName} } return loadedUser, nil } // GetAll returns all Users func (s *DatabaseUserStore) GetAll() ([]rbac.LoadedUser, error) { var loadedUsers []rbac.LoadedUser client, ctx, cancel := database.GetMongoConnection() defer cancel() defer client.Disconnect(ctx) db := client.Database(database.DatabaseName) collection := db.Collection(s.userStoreName) cursor, err := collection.Find(ctx, bson.D{}) if err != nil { return nil, err } defer cursor.Close(ctx) err = cursor.All(ctx, &loadedUsers) if err != nil { log.Printf("Failed marshalling %v", err) return nil, errors.ErrCouldNotMarshall{StoreName: s.userStoreName} } return loadedUsers, nil } // Update updates the User. func (s *DatabaseUserStore) Update(userToUpdate rbac.User) error { var updatedLoadedUser rbac.LoadedUser client, ctx, cancel := database.GetMongoConnection() defer cancel() defer client.Disconnect(ctx) update := bson.D{primitive.E{Key: "$set", Value: userToUpdate}} upsert := false after := options.After opt := options.FindOneAndUpdateOptions{ Upsert: &upsert, ReturnDocument: &after, } err := client.Database(database.DatabaseName). Collection(s.userStoreName). FindOneAndUpdate( ctx, bson.M{"_id": userToUpdate.ID().String()}, update, &opt). Decode(&updatedLoadedUser) if err != nil { log.Printf("Could not update User: %v", err) return errors.ErrCouldNotUpdate{StoreName: s.userStoreName} } return nil }