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 }