diff --git a/Makefile b/Makefile index 61e5e0be7b..c5c753c3ae 100644 --- a/Makefile +++ b/Makefile @@ -284,9 +284,9 @@ postgres: postgres:13-alpine || docker start goalert-postgres regendb: bin/resetdb bin/goalert config.json.bak - ./bin/resetdb -with-rand-data -admin-id=00000000-0000-0000-0000-000000000000 + ./bin/resetdb -with-rand-data -admin-id=00000000-0000-0000-0000-000000000001 test -f config.json.bak && bin/goalert set-config --allow-empty-data-encryption-key "--db-url=$(DB_URL)" 1 { dedupStr = parts[1] diff --git a/notification/store.go b/notification/store.go index cd6f5c73ee..a997ad21a0 100644 --- a/notification/store.go +++ b/notification/store.go @@ -17,8 +17,8 @@ import ( "github.com/target/goalert/validation" "github.com/target/goalert/validation/validate" + "github.com/google/uuid" "github.com/pkg/errors" - uuid "github.com/satori/go.uuid" ) const minTimeBetweenTests = time.Minute @@ -291,7 +291,7 @@ func (db *DB) SendContactMethodTest(ctx context.Context, id string) error { return validation.NewFieldError("ContactMethod", "test message rate-limit exceeded") } - vID := uuid.NewV4().String() + vID := uuid.New().String() _, err = tx.StmtContext(ctx, db.insertTestNotification).ExecContext(ctx, vID, id) if err != nil { return err @@ -324,7 +324,7 @@ func (db *DB) SendContactMethodVerification(ctx context.Context, cmID string) er return validation.NewFieldError("ContactMethod", fmt.Sprintf("Too many messages! Please try again in %.0f minute(s)", minTimeBetweenTests.Minutes())) } - vcID := uuid.NewV4().String() + vcID := uuid.New().String() code := db.rand.Intn(900000) + 100000 _, err = tx.StmtContext(ctx, db.setVerificationCode).ExecContext(ctx, vcID, cmID, code) if err != nil { diff --git a/notificationchannel/channel.go b/notificationchannel/channel.go index 8b54e8d272..62be7967b0 100644 --- a/notificationchannel/channel.go +++ b/notificationchannel/channel.go @@ -1,9 +1,8 @@ package notificationchannel import ( + "github.com/google/uuid" "github.com/target/goalert/validation/validate" - - uuid "github.com/satori/go.uuid" ) type Channel struct { @@ -15,7 +14,7 @@ type Channel struct { func (c Channel) Normalize() (*Channel, error) { if c.ID == "" { - c.ID = uuid.NewV4().String() + c.ID = uuid.New().String() } err := validate.Many( diff --git a/notificationchannel/store.go b/notificationchannel/store.go index ab414dede6..1991927586 100644 --- a/notificationchannel/store.go +++ b/notificationchannel/store.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/permission" "github.com/target/goalert/util" "github.com/target/goalert/util/sqlutil" @@ -124,7 +124,7 @@ func (db *DB) MapToID(ctx context.Context, tx *sql.Tx, c *Channel) (uuid.UUID, e if !id.Valid { // create new one id.Valid = true - id.UUID = uuid.NewV4() + id.UUID = uuid.New() _, err = tx.StmtContext(ctx, db.create).ExecContext(ctx, id, n.Name, n.Type, n.Value) if err != nil { return uuid.UUID{}, fmt.Errorf("create new NC: %w", err) diff --git a/oncall/store.go b/oncall/store.go index dcecb55131..aeb97174b1 100644 --- a/oncall/store.go +++ b/oncall/store.go @@ -6,7 +6,8 @@ import ( "fmt" "time" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" + "github.com/pkg/errors" "github.com/target/goalert/assignment" "github.com/target/goalert/override" "github.com/target/goalert/permission" @@ -15,8 +16,6 @@ import ( "github.com/target/goalert/util" "github.com/target/goalert/util/sqlutil" "github.com/target/goalert/validation/validate" - - "github.com/pkg/errors" ) // Store allows retrieving and calculating on-call information. @@ -314,7 +313,7 @@ func (db *DB) HistoryBySchedule(ctx context.Context, scheduleID string, start, e ov.RemoveUserID = rem.String overrides = append(overrides, ov) } - id, err := uuid.FromString(scheduleID) + id, err := uuid.Parse(scheduleID) if err != nil { return nil, errors.Wrap(err, "parse schedule ID") } diff --git a/override/store.go b/override/store.go index 8360103ec2..f3885a6c39 100644 --- a/override/store.go +++ b/override/store.go @@ -13,7 +13,7 @@ import ( "github.com/target/goalert/validation" "github.com/target/goalert/validation/validate" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) // Store is used to manage active overrides. @@ -203,7 +203,7 @@ func (db *DB) CreateUserOverrideTx(ctx context.Context, tx *sql.Tx, o *UserOverr if !n.End.After(time.Now()) { return nil, validation.NewFieldError("End", "must be in the future") } - n.ID = uuid.NewV4().String() + n.ID = uuid.New().String() var add, rem sql.NullString if n.AddUserID != "" { add.Valid = true diff --git a/remotemonitor/requestid.go b/remotemonitor/requestid.go index a457be2cf3..190db1830b 100644 --- a/remotemonitor/requestid.go +++ b/remotemonitor/requestid.go @@ -4,7 +4,7 @@ import ( "log" "net/http" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) type requestIDTransport struct { @@ -13,7 +13,7 @@ type requestIDTransport struct { func (r *requestIDTransport) RoundTrip(req *http.Request) (*http.Response, error) { q := req.URL.Query() - q.Set("x-request-id", uuid.NewV4().String()) + q.Set("x-request-id", uuid.New().String()) req.URL.RawQuery = q.Encode() log.Println(req.Method, req.URL.String()) diff --git a/schedule/oncallnotificationrule.go b/schedule/oncallnotificationrule.go index 910308c1ce..f74a8eaded 100644 --- a/schedule/oncallnotificationrule.go +++ b/schedule/oncallnotificationrule.go @@ -8,7 +8,7 @@ import ( "time" "github.com/99designs/gqlgen/graphql" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/util/timeutil" "github.com/target/goalert/validation" ) @@ -87,7 +87,7 @@ func (r *RuleID) UnmarshalText(data []byte) error { } var err error - r.scheduleID, err = uuid.FromString(s[:36]) + r.scheduleID, err = uuid.Parse(s[:36]) if err != nil { return err } diff --git a/schedule/rotation/store.go b/schedule/rotation/store.go index bef4f415c1..d72786b039 100644 --- a/schedule/rotation/store.go +++ b/schedule/rotation/store.go @@ -5,8 +5,8 @@ import ( "database/sql" "sort" + "github.com/google/uuid" "github.com/pkg/errors" - uuid "github.com/satori/go.uuid" "github.com/target/goalert/assignment" "github.com/target/goalert/permission" "github.com/target/goalert/util" @@ -415,7 +415,7 @@ func (db *DB) CreateRotationTx(ctx context.Context, tx *sql.Tx, r *Rotation) (*R stmt = tx.Stmt(stmt) } - n.ID = uuid.NewV4().String() + n.ID = uuid.New().String() _, err = stmt.ExecContext(ctx, n.ID, n.Name, n.Description, n.Type, n.Start, n.ShiftLength, n.Start.Location().String()) if err != nil { @@ -722,7 +722,7 @@ func (db *DB) AddParticipantTx(ctx context.Context, tx *sql.Tx, p *Participant) stmt = tx.Stmt(stmt) } - n.ID = uuid.NewV4().String() + n.ID = uuid.New().String() row := stmt.QueryRowContext(ctx, n.ID, n.RotationID, n.Target.TargetID()) err = row.Scan(&n.Position) @@ -867,7 +867,7 @@ func (db *DB) AddRotationUsersTx(ctx context.Context, tx *sql.Tx, rotationID str stmt = tx.StmtContext(ctx, stmt) } for _, userID := range userIDs { - _, err = stmt.ExecContext(ctx, uuid.NewV4().String(), rotationID, userID) + _, err = stmt.ExecContext(ctx, uuid.New().String(), rotationID, userID) if err != nil { return err } diff --git a/schedule/rule/store.go b/schedule/rule/store.go index 89735f9dd8..ba438c6da3 100644 --- a/schedule/rule/store.go +++ b/schedule/rule/store.go @@ -11,7 +11,7 @@ import ( "github.com/target/goalert/util/sqlutil" "github.com/target/goalert/validation/validate" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) type Store interface { @@ -235,7 +235,7 @@ func (db *DB) _Add(ctx context.Context, s *sql.Stmt, r *Rule) (*Rule, error) { return nil, err } - n.ID = uuid.NewV4().String() + n.ID = uuid.New().String() _, err = s.ExecContext(ctx, n.readFields()...) if err != nil { return nil, err diff --git a/schedule/storedata.go b/schedule/storedata.go index e5f00a4b1b..dc942bda62 100644 --- a/schedule/storedata.go +++ b/schedule/storedata.go @@ -5,7 +5,7 @@ import ( "database/sql" "encoding/json" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/util/jsonutil" ) diff --git a/schedule/storeoncallnotifications.go b/schedule/storeoncallnotifications.go index cf63063346..fa45f48e0f 100644 --- a/schedule/storeoncallnotifications.go +++ b/schedule/storeoncallnotifications.go @@ -5,7 +5,7 @@ import ( "database/sql" "fmt" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/permission" "github.com/target/goalert/util/timeutil" "github.com/target/goalert/validation" diff --git a/schedule/storetemporaryschedules.go b/schedule/storetemporaryschedules.go index 79b1a989da..0ba9af20be 100644 --- a/schedule/storetemporaryschedules.go +++ b/schedule/storetemporaryschedules.go @@ -5,7 +5,7 @@ import ( "database/sql" "time" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/permission" "github.com/target/goalert/util/sqlutil" "github.com/target/goalert/validation" diff --git a/service/store.go b/service/store.go index f669de3f66..0db4741f13 100644 --- a/service/store.go +++ b/service/store.go @@ -3,12 +3,13 @@ package service import ( "context" "database/sql" + "github.com/target/goalert/permission" "github.com/target/goalert/util" "github.com/target/goalert/util/sqlutil" "github.com/target/goalert/validation/validate" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) type Store interface { @@ -181,7 +182,7 @@ func (db *DB) CreateServiceTx(ctx context.Context, tx *sql.Tx, s *Service) (*Ser return nil, err } - n.ID = uuid.NewV4().String() + n.ID = uuid.New().String() stmt := db.insert if tx != nil { stmt = tx.Stmt(stmt) diff --git a/smoketest/harness/datagen.go b/smoketest/harness/datagen.go index b60eb12c4e..a6d8919f74 100644 --- a/smoketest/harness/datagen.go +++ b/smoketest/harness/datagen.go @@ -8,8 +8,8 @@ import ( "sync" "testing" + "github.com/google/uuid" "github.com/pkg/errors" - uuid "github.com/satori/go.uuid" "github.com/ttacon/libphonenumber" ) @@ -89,7 +89,7 @@ func (d *DataGen) GetWithArg(arg, id string) string { // GenUUID will return a random UUID. func GenUUID() string { - return uuid.NewV4().String() + return uuid.New().String() } // GenPhoneCC will return a random phone number with supplied country code diff --git a/smoketest/harness/graphql.go b/smoketest/harness/graphql.go index 9611021ffb..c7522d24f6 100644 --- a/smoketest/harness/graphql.go +++ b/smoketest/harness/graphql.go @@ -20,7 +20,7 @@ import ( ) // DefaultGraphQLAdminUserID is the UserID created & used for GraphQL calls by default. -const DefaultGraphQLAdminUserID = "00000000-0000-0000-0000-000000000000" +const DefaultGraphQLAdminUserID = "00000000-0000-0000-0000-000000000002" func (h *Harness) insertGraphQLUser(userID string) string { h.t.Helper() diff --git a/smoketest/harness/harness.go b/smoketest/harness/harness.go index 98463eadde..e5e7069fea 100644 --- a/smoketest/harness/harness.go +++ b/smoketest/harness/harness.go @@ -19,11 +19,11 @@ import ( "text/template" "time" + "github.com/google/uuid" "github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/pgx/v4/stdlib" "github.com/pkg/errors" - uuid "github.com/satori/go.uuid" "github.com/target/goalert/alert" "github.com/target/goalert/app" "github.com/target/goalert/config" @@ -157,7 +157,7 @@ func NewStoppedHarness(t *testing.T, initSQL string, sqlData interface{}, migrat t.Logf("Using DB URL: %s", dbURL) start := time.Now() - name := strings.Replace("smoketest_"+time.Now().Format("2006_01_02_15_04_05")+uuid.NewV4().String(), "-", "", -1) + name := strings.Replace("smoketest_"+time.Now().Format("2006_01_02_15_04_05")+uuid.New().String(), "-", "", -1) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -618,7 +618,7 @@ func (h *Harness) CreateUser() (u *user.User) { permission.SudoContext(context.Background(), func(ctx context.Context) { u, err = h.backend.UserStore.Insert(ctx, &user.User{ Name: fmt.Sprintf("Generated%d", h.userGeneratedIndex), - ID: uuid.NewV4().String(), + ID: uuid.New().String(), Role: permission.RoleUser, Email: fmt.Sprintf("generated%d@example.com", h.userGeneratedIndex), }) diff --git a/smoketest/migrations_test.go b/smoketest/migrations_test.go index 7c68ffb2cd..2afbc9df38 100644 --- a/smoketest/migrations_test.go +++ b/smoketest/migrations_test.go @@ -16,8 +16,8 @@ import ( "text/template" "time" + "github.com/google/uuid" _ "github.com/jackc/pgx/v4/stdlib" // import db driver - uuid "github.com/satori/go.uuid" "github.com/target/goalert/migrate" "github.com/target/goalert/smoketest/harness" "github.com/target/goalert/util/sqlutil" @@ -537,7 +537,7 @@ func TestMigrations(t *testing.T) { t.Fatal("failed to open db:", err) } defer db.Close() - dbName := strings.Replace("migrations_smoketest_"+time.Now().Format("2006_01_02_03_04_05")+uuid.NewV4().String(), "-", "", -1) + dbName := strings.Replace("migrations_smoketest_"+time.Now().Format("2006_01_02_03_04_05")+uuid.New().String(), "-", "", -1) _, err = db.Exec("create database " + sqlutil.QuoteID(dbName)) if err != nil { diff --git a/smoketest/oncallnotify_test.go b/smoketest/oncallnotify_test.go index 0312a51cca..99073f19c1 100644 --- a/smoketest/oncallnotify_test.go +++ b/smoketest/oncallnotify_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/target/goalert/assignment" "github.com/target/goalert/permission" @@ -46,7 +46,7 @@ func TestOnCallNotify(t *testing.T) { ctx := permission.SystemContext(context.Background(), "Test") _, err := h.App().ScheduleRuleStore.CreateRuleTx(ctx, nil, &rule.Rule{ - ID: uuid.NewV4().String(), + ID: uuid.New().String(), ScheduleID: h.UUID("sid"), WeekdayFilter: timeutil.EveryDay(), Target: assignment.UserTarget(h.UUID("uid2")), diff --git a/switchover/handler.go b/switchover/handler.go index ade5204705..ac2ad320b4 100644 --- a/switchover/handler.go +++ b/switchover/handler.go @@ -13,8 +13,8 @@ import ( "github.com/target/goalert/util/log" "github.com/target/goalert/util/sqlutil" + "github.com/google/uuid" "github.com/pkg/errors" - uuid "github.com/satori/go.uuid" ) type Handler struct { @@ -49,7 +49,7 @@ type App interface { func NewHandler(ctx context.Context, oldC, newC driver.Connector, oldURL, newURL string) (*Handler, error) { h := &Handler{ - id: uuid.NewV4().String(), + id: uuid.New().String(), stateCh: make(chan State), statusCh: make(chan *Status), controlCh: make(chan *DeadlineConfig), diff --git a/user/cache.go b/user/cache.go index 1e657a7f29..a714acd658 100644 --- a/user/cache.go +++ b/user/cache.go @@ -9,7 +9,7 @@ import ( "time" "github.com/golang/groupcache" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/permission" ) @@ -28,11 +28,16 @@ type ExistanceChecker interface { type checker map[uuid.UUID]struct{} -func (c checker) UserExistsString(id string) bool { - if id == "" { +func (c checker) UserExistsString(idStr string) bool { + if idStr == "" { return false } - return c.UserExistsUUID(uuid.FromStringOrNil(id)) + id, err := uuid.Parse(idStr) + if err != nil { + return false + } + + return c.UserExistsUUID(id) } func (c checker) UserExistsUUID(id uuid.UUID) bool { _, ok := c[id]; return ok } diff --git a/user/contactmethod/contactmethod.go b/user/contactmethod/contactmethod.go index 1459f17c1f..6e9fe6e85e 100644 --- a/user/contactmethod/contactmethod.go +++ b/user/contactmethod/contactmethod.go @@ -4,7 +4,7 @@ import ( "database/sql" "time" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/validation/validate" ) @@ -27,7 +27,7 @@ func (c ContactMethod) LastTestVerifyAt() time.Time { return c.lastTestVerifyAt. // and setting carrier to "" (for non-phone types). func (c ContactMethod) Normalize() (*ContactMethod, error) { if c.ID == "" { - c.ID = uuid.NewV4().String() + c.ID = uuid.New().String() } err := validate.Many( validate.UUID("ID", c.ID), diff --git a/user/notificationrule/store.go b/user/notificationrule/store.go index a2e6372f4e..2d92406c00 100644 --- a/user/notificationrule/store.go +++ b/user/notificationrule/store.go @@ -3,13 +3,12 @@ package notificationrule import ( "context" "database/sql" + + "github.com/google/uuid" "github.com/target/goalert/permission" "github.com/target/goalert/util" "github.com/target/goalert/util/sqlutil" - "github.com/target/goalert/validation/validate" - - uuid "github.com/satori/go.uuid" ) // Store allows the lookup and management of NotificationRules. @@ -100,7 +99,7 @@ func (db *DB) CreateTx(ctx context.Context, tx *sql.Tx, n *NotificationRule) (*N return nil, err } - n.ID = uuid.NewV4().String() + n.ID = uuid.New().String() _, err = wrapTx(ctx, tx, db.insert).ExecContext(ctx, n.ID, n.UserID, n.DelayMinutes, n.ContactMethodID) if err != nil { diff --git a/user/store.go b/user/store.go index 9aa3ac120a..68083ac939 100644 --- a/user/store.go +++ b/user/store.go @@ -9,7 +9,7 @@ import ( "time" "github.com/golang/groupcache" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" "github.com/target/goalert/permission" "github.com/target/goalert/retry" "github.com/target/goalert/util" diff --git a/user/user.go b/user/user.go index 4b447f2ce3..a3204b0b44 100644 --- a/user/user.go +++ b/user/user.go @@ -9,7 +9,7 @@ import ( "github.com/target/goalert/permission" "github.com/target/goalert/validation/validate" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) // A User is the base information of a user of the system. Authentication details are stored @@ -97,7 +97,7 @@ func (u *User) fields() []interface{} { func (u User) Normalize() (*User, error) { var err error if u.ID == "" { - u.ID = uuid.NewV4().String() + u.ID = uuid.New().String() } if u.Email != "" { err = validate.Email("Email", u.Email) diff --git a/util/contextcache.go b/util/contextcache.go index 5ef907fac4..4ecb44a42f 100644 --- a/util/contextcache.go +++ b/util/contextcache.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) type cacheableKey string @@ -12,7 +12,7 @@ type cacheableKey string const cacheableKeyID = cacheableKey("cache-id") func cacheableContext(ctx context.Context) context.Context { - return context.WithValue(ctx, cacheableKeyID, uuid.NewV4().String()) + return context.WithValue(ctx, cacheableKeyID, uuid.New().String()) } // WrapCacheableContext will make all request contexts cacheable, to be used with diff --git a/util/sqlutil/nulluuid.go b/util/sqlutil/nulluuid.go index 52812bfa62..317d84e457 100644 --- a/util/sqlutil/nulluuid.go +++ b/util/sqlutil/nulluuid.go @@ -4,7 +4,7 @@ import ( "database/sql/driver" "fmt" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" ) type NullUUID struct { @@ -17,7 +17,7 @@ func (u NullUUID) Value() (driver.Value, error) { return nil, nil } - return u.UUID.Bytes(), nil + return []byte(u.UUID[:]), nil } func (u *NullUUID) Scan(src interface{}) (err error) { @@ -29,13 +29,13 @@ func (u *NullUUID) Scan(src interface{}) (err error) { switch s := src.(type) { case string: - u.UUID, err = uuid.FromString(s) + u.UUID, err = uuid.Parse(s) case []byte: if len(s) == 16 { u.UUID, err = uuid.FromBytes(s) break } - u.UUID, err = uuid.FromString(string(s)) + u.UUID, err = uuid.Parse(string(s)) default: return fmt.Errorf("unknown format for UUID: %T", s) } diff --git a/validation/validate/uuid.go b/validation/validate/uuid.go index e71a1ce3d9..cc2efd163c 100644 --- a/validation/validate/uuid.go +++ b/validation/validate/uuid.go @@ -2,16 +2,22 @@ package validate import ( "database/sql" - "github.com/target/goalert/validation" "strconv" - uuid "github.com/satori/go.uuid" + "github.com/google/uuid" + "github.com/target/goalert/validation" ) // UUID will validate a UUID, returning a FieldError // if invalid. func UUID(fname, u string) error { - _, err := uuid.FromString(u) + if len(u) != 36 { + // Format check only required to ensure string IDs are valid when being passed to DB. + // + // We can remove this check once we switch to uuid.UUID in structs everywhere. + return validation.NewFieldError(fname, "must be valid UUID: format must be xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") + } + _, err := uuid.Parse(u) if err != nil { return validation.NewFieldError(fname, "must be a valid UUID: "+err.Error()) }