github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/database/gormdb.go (about)

     1  package database
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/quickfeed/quickfeed/kit/score"
     7  	"github.com/quickfeed/quickfeed/qf"
     8  	"go.uber.org/zap"
     9  	"gorm.io/driver/sqlite"
    10  	"gorm.io/gorm"
    11  	"gorm.io/gorm/schema"
    12  )
    13  
    14  var (
    15  	// ErrDuplicateIdentity is returned when trying to associate a remote identity
    16  	// with a user account and the identity is already in use.
    17  	ErrDuplicateIdentity = errors.New("remote identity registered with another user")
    18  	// ErrEmptyGroup is returned when trying to create a group without users.
    19  	ErrEmptyGroup = errors.New("cannot create group without users")
    20  	// ErrDuplicateGroup is returned when trying to create a group with the same
    21  	// name as a previously registered group.
    22  	ErrDuplicateGroup = errors.New("group with this name already registered")
    23  	// ErrUpdateGroup is returned when updating a group's enrollment fails.
    24  	ErrUpdateGroup = errors.New("failed to update group enrollment")
    25  	// ErrCourseExists is returned when trying to create an association in
    26  	// the database for a DirectoryId that already exists in the database.
    27  	ErrCourseExists = errors.New("course already exists on git provider")
    28  	// ErrInsufficientAccess is returned when trying to update database
    29  	// with insufficient access privileges.
    30  	ErrInsufficientAccess = errors.New("user must be admin to perform this operation")
    31  	// ErrCreateRepo is returned when trying to create repository with wrong argument.
    32  	ErrCreateRepo = errors.New("failed to create repository; invalid arguments")
    33  	// ErrNotEnrolled is returned when the requested user or group do not have
    34  	// the expected association with the given course
    35  	ErrNotEnrolled = errors.New("user or group not enrolled in the course")
    36  )
    37  
    38  // GormDB implements the Database interface.
    39  type GormDB struct {
    40  	conn *gorm.DB
    41  }
    42  
    43  // NewGormDB creates a new gorm database using the provided driver.
    44  func NewGormDB(path string, logger *zap.Logger) (*GormDB, error) {
    45  	// We are conservative and use transactions for create/update/delete operations.
    46  	conn, err := gorm.Open(sqlite.Open(path), &gorm.Config{ // skipcq: GO-W1004
    47  		Logger:                 NewGORMLogger(logger),
    48  		SkipDefaultTransaction: false,
    49  	})
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	schema.RegisterSerializer("timestamp", &TimestampSerializer{})
    55  
    56  	if err := conn.AutoMigrate(
    57  		&qf.User{},
    58  		&qf.Course{},
    59  		&qf.Enrollment{},
    60  		&qf.Assignment{},
    61  		&qf.Submission{},
    62  		&qf.Group{},
    63  		&qf.Repository{},
    64  		&qf.UsedSlipDays{},
    65  		&qf.GradingBenchmark{},
    66  		&qf.GradingCriterion{},
    67  		&qf.Review{},
    68  		&qf.Issue{},
    69  		&qf.Task{},
    70  		&qf.PullRequest{},
    71  		&score.BuildInfo{},
    72  		&score.Score{},
    73  	); err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	return &GormDB{conn}, nil
    78  }
    79  
    80  func (db *GormDB) Close() error {
    81  	sqlDB, err := db.conn.DB()
    82  	if err != nil {
    83  		return err
    84  	}
    85  	return sqlDB.Close()
    86  }