diff --git a/README.md b/README.md index 9cb7bbba..7df02a02 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,14 @@ PSQL_DSN="postgresql://?host=/var/run/postgresql&sslmode=disable&dbname=nidus-sy ``` This will generate a bunch of files. They're already committed, you only need this if you change the database schema in some way. + +### goose + +This uses [goose](https://github.com/pressly/goose). You can use the goose command line to check status and make changes + +```sh +> cd migrations +> GOOSE_DRIVER=postgres GOOSE_DBSTRING="dbname=nidus-sync sslmode=disable" goose status +> GOOSE_DRIVER=postgres GOOSE_DBSTRING="dbname=nidus-sync sslmode=disable" goose down +> GOOSE_DRIVER=postgres GOOSE_DBSTRING="dbname=nidus-sync sslmode=disable" goose up +``` diff --git a/arcgis-go b/arcgis-go index 5bc087a1..a99b4a72 160000 --- a/arcgis-go +++ b/arcgis-go @@ -1 +1 @@ -Subproject commit 5bc087a120a5dab09789b9abe913fd01b735dcff +Subproject commit a99b4a72b2bb3dcff642209f029eb4e7d746fa8d diff --git a/arcgis.go b/arcgis.go index 77674623..98e826e6 100644 --- a/arcgis.go +++ b/arcgis.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "log/slog" @@ -19,6 +20,8 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/models" "github.com/Gleipnir-Technology/nidus-sync/sql" "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" + "github.com/jackc/pgx/v5" ) var CodeVerifier string = "random_secure_string_min_43_chars_long_should_be_stored_in_session" @@ -63,7 +66,7 @@ func generateCodeVerifier() string { } // Find out what we can about this user -func getArcgisUserData(access_token string, expires time.Time, refresh_token string) { +func updateArcgisUserData(ctx context.Context, user *models.User, access_token string, expires time.Time, refresh_token string) { client := arcgis.NewArcGIS( arcgis.AuthenticatorOAuth{ AccessToken: access_token, @@ -71,15 +74,60 @@ func getArcgisUserData(access_token string, expires time.Time, refresh_token str RefreshToken: refresh_token, }, ) - /*portal, err := client.PortalsSelf() + portal, err := client.PortalsSelf() if err != nil { slog.Error("Failed to get ArcGIS user data", slog.String("err", err.Error())) return } slog.Info("Got portals data", slog.String("Username", portal.User.Username), - slog.String("ID", portal.ID)) - */ + slog.String("user_id", portal.User.ID), + slog.String("org_id", portal.User.OrgID), + slog.String("org_name", portal.Name), + slog.String("license_type_id", portal.User.UserLicenseTypeID)) + + _, err = sql.UpdateOauthTokenOrg(portal.User.ID, portal.User.UserLicenseTypeID, refresh_token).Exec(ctx, PGInstance.BobDB) + if err != nil { + slog.Error("Failed to update oauth token portal data", slog.String("err", err.Error())) + return + } + var org *models.Organization + orgs, err := models.Organizations.Query(models.SelectWhere.Organizations.ArcgisName.EQ(portal.Name)).All(ctx, PGInstance.BobDB) + switch len(orgs) { + case 0: + setter := models.OrganizationSetter{ + Name: omitnull.From(portal.Name), + ArcgisID: omitnull.From(portal.User.OrgID), + ArcgisName: omitnull.From(portal.Name), + } + org, err = models.Organizations.Insert(&setter).One(ctx, PGInstance.BobDB) + if err != nil { + slog.Error("Failed to create new organization", slog.String("err", err.Error())) + return + } + slog.Info("Created new organization", slog.Int("org_id", int(org.ID))) + case 1: + org = orgs[0] + slog.Info("Organization already exists") + default: + slog.Error("Got too many organizations, bailing") + return + + } + if err != nil { + LogErrorTypeInfo(err) + if errors.Is(err, pgx.ErrNoRows) { + } else { + slog.Error("Failed to query for existing org", slog.String("err", err.Error())) + return + } + } + err = org.AttachUser(ctx, PGInstance.BobDB, user) + if err != nil { + slog.Error("Failed to attach user to organization", slog.String("err", err.Error()), slog.Int("user_id", int(user.ID)), slog.Int("org_id", int(org.ID))) + return + } + search, err := client.Search("Fieldseeker") if err != nil { slog.Error("Failed to get search FieldseekerGIS data", slog.String("err", err.Error())) @@ -152,7 +200,7 @@ func handleOauthAccessCode(ctx context.Context, user *models.User, code string) if err != nil { return fmt.Errorf("Failed to save token to database: %v", err) } - go getArcgisUserData(tokenResponse.AccessToken, expires, tokenResponse.RefreshToken) + go updateArcgisUserData(context.Background(), user, tokenResponse.AccessToken, expires, tokenResponse.RefreshToken) return nil } @@ -166,3 +214,7 @@ func hasFieldseekerConnection(ctx context.Context, user *models.User) (bool, err func redirectURL() string { return BaseURL + "/arcgis/oauth/callback" } + +// This is a goroutine that is in charge of getting Fieldseeker data and keeping it fresh. +func refreshFieldseekerData(newOauthCh <-chan int, done <-chan struct{}) { +} diff --git a/dbinfo/oauth_token.bob.go b/dbinfo/oauth_token.bob.go index f25b58f1..0762c7ac 100644 --- a/dbinfo/oauth_token.bob.go +++ b/dbinfo/oauth_token.bob.go @@ -69,6 +69,24 @@ var OauthTokens = Table[ Generated: false, AutoIncr: false, }, + ArcgisID: column{ + Name: "arcgis_id", + DBType: "text", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + ArcgisLicenseTypeID: column{ + Name: "arcgis_license_type_id", + DBType: "text", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, }, Indexes: oauthTokenIndexes{ OauthTokenPkey: index{ @@ -110,17 +128,19 @@ var OauthTokens = Table[ } type oauthTokenColumns struct { - ID column - AccessToken column - Expires column - RefreshToken column - Username column - UserID column + ID column + AccessToken column + Expires column + RefreshToken column + Username column + UserID column + ArcgisID column + ArcgisLicenseTypeID column } func (c oauthTokenColumns) AsSlice() []column { return []column{ - c.ID, c.AccessToken, c.Expires, c.RefreshToken, c.Username, c.UserID, + c.ID, c.AccessToken, c.Expires, c.RefreshToken, c.Username, c.UserID, c.ArcgisID, c.ArcgisLicenseTypeID, } } diff --git a/dbinfo/organization.bob.go b/dbinfo/organization.bob.go index 77516633..b278235a 100644 --- a/dbinfo/organization.bob.go +++ b/dbinfo/organization.bob.go @@ -33,6 +33,24 @@ var Organizations = Table[ Generated: false, AutoIncr: false, }, + ArcgisID: column{ + Name: "arcgis_id", + DBType: "text", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + ArcgisName: column{ + Name: "arcgis_name", + DBType: "text", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, }, Indexes: organizationIndexes{ OrganizationPkey: index{ @@ -63,13 +81,15 @@ var Organizations = Table[ } type organizationColumns struct { - ID column - Name column + ID column + Name column + ArcgisID column + ArcgisName column } func (c organizationColumns) AsSlice() []column { return []column{ - c.ID, c.Name, + c.ID, c.Name, c.ArcgisID, c.ArcgisName, } } diff --git a/errors.go b/errors.go new file mode 100644 index 00000000..1e2ddd2e --- /dev/null +++ b/errors.go @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "log/slog" + "reflect" +) + +func LogErrorTypeInfo(err error) { + if err == nil { + slog.Info("Error is nil") + return + } + + // Log current error type + errType := reflect.TypeOf(err) + slog.Info("Error type info", + "type", errType.String(), + "pkgPath", errType.PkgPath(), + "error", err.Error()) + + // Recursively log wrapped errors + wrappedErr := errors.Unwrap(err) + if wrappedErr != nil { + slog.Info("Contains wrapped error") + LogErrorTypeInfo(wrappedErr) + } +} diff --git a/factory/bobfactory_main.bob.go b/factory/bobfactory_main.bob.go index 6340638f..56ddd221 100644 --- a/factory/bobfactory_main.bob.go +++ b/factory/bobfactory_main.bob.go @@ -76,6 +76,8 @@ func (f *Factory) FromExistingOauthToken(m *models.OauthToken) *OauthTokenTempla o.RefreshToken = func() string { return m.RefreshToken } o.Username = func() string { return m.Username } o.UserID = func() int32 { return m.UserID } + o.ArcgisID = func() null.Val[string] { return m.ArcgisID } + o.ArcgisLicenseTypeID = func() null.Val[string] { return m.ArcgisLicenseTypeID } ctx := context.Background() if m.R.UserUser != nil { @@ -106,6 +108,8 @@ func (f *Factory) FromExistingOrganization(m *models.Organization) *Organization o.ID = func() int32 { return m.ID } o.Name = func() null.Val[string] { return m.Name } + o.ArcgisID = func() null.Val[string] { return m.ArcgisID } + o.ArcgisName = func() null.Val[string] { return m.ArcgisName } ctx := context.Background() if len(m.R.User) > 0 { diff --git a/factory/oauth_token.bob.go b/factory/oauth_token.bob.go index 18d06698..de841132 100644 --- a/factory/oauth_token.bob.go +++ b/factory/oauth_token.bob.go @@ -9,7 +9,9 @@ import ( "time" models "github.com/Gleipnir-Technology/nidus-sync/models" + "github.com/aarondl/opt/null" "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" "github.com/jaswdr/faker/v2" "github.com/stephenafamo/bob" ) @@ -35,12 +37,14 @@ func (mods OauthTokenModSlice) Apply(ctx context.Context, n *OauthTokenTemplate) // OauthTokenTemplate is an object representing the database table. // all columns are optional and should be set by mods type OauthTokenTemplate struct { - ID func() int32 - AccessToken func() string - Expires func() time.Time - RefreshToken func() string - Username func() string - UserID func() int32 + ID func() int32 + AccessToken func() string + Expires func() time.Time + RefreshToken func() string + Username func() string + UserID func() int32 + ArcgisID func() null.Val[string] + ArcgisLicenseTypeID func() null.Val[string] r oauthTokenR f *Factory @@ -103,6 +107,14 @@ func (o OauthTokenTemplate) BuildSetter() *models.OauthTokenSetter { val := o.UserID() m.UserID = omit.From(val) } + if o.ArcgisID != nil { + val := o.ArcgisID() + m.ArcgisID = omitnull.FromNull(val) + } + if o.ArcgisLicenseTypeID != nil { + val := o.ArcgisLicenseTypeID() + m.ArcgisLicenseTypeID = omitnull.FromNull(val) + } return m } @@ -143,6 +155,12 @@ func (o OauthTokenTemplate) Build() *models.OauthToken { if o.UserID != nil { m.UserID = o.UserID() } + if o.ArcgisID != nil { + m.ArcgisID = o.ArcgisID() + } + if o.ArcgisLicenseTypeID != nil { + m.ArcgisLicenseTypeID = o.ArcgisLicenseTypeID() + } o.setModelRels(m) @@ -308,6 +326,8 @@ func (m oauthTokenMods) RandomizeAllColumns(f *faker.Faker) OauthTokenMod { OauthTokenMods.RandomRefreshToken(f), OauthTokenMods.RandomUsername(f), OauthTokenMods.RandomUserID(f), + OauthTokenMods.RandomArcgisID(f), + OauthTokenMods.RandomArcgisLicenseTypeID(f), } } @@ -497,6 +517,112 @@ func (m oauthTokenMods) RandomUserID(f *faker.Faker) OauthTokenMod { }) } +// Set the model columns to this value +func (m oauthTokenMods) ArcgisID(val null.Val[string]) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisID = func() null.Val[string] { return val } + }) +} + +// Set the Column from the function +func (m oauthTokenMods) ArcgisIDFunc(f func() null.Val[string]) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisID = f + }) +} + +// Clear any values for the column +func (m oauthTokenMods) UnsetArcgisID() OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m oauthTokenMods) RandomArcgisID(f *faker.Faker) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisID = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m oauthTokenMods) RandomArcgisIDNotNull(f *faker.Faker) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisID = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m oauthTokenMods) ArcgisLicenseTypeID(val null.Val[string]) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisLicenseTypeID = func() null.Val[string] { return val } + }) +} + +// Set the Column from the function +func (m oauthTokenMods) ArcgisLicenseTypeIDFunc(f func() null.Val[string]) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisLicenseTypeID = f + }) +} + +// Clear any values for the column +func (m oauthTokenMods) UnsetArcgisLicenseTypeID() OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisLicenseTypeID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m oauthTokenMods) RandomArcgisLicenseTypeID(f *faker.Faker) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisLicenseTypeID = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m oauthTokenMods) RandomArcgisLicenseTypeIDNotNull(f *faker.Faker) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.ArcgisLicenseTypeID = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + func (m oauthTokenMods) WithParentsCascading() OauthTokenMod { return OauthTokenModFunc(func(ctx context.Context, o *OauthTokenTemplate) { if isDone, _ := oauthTokenWithParentsCascadingCtx.Value(ctx); isDone { diff --git a/factory/organization.bob.go b/factory/organization.bob.go index 497959fc..b63e41f6 100644 --- a/factory/organization.bob.go +++ b/factory/organization.bob.go @@ -36,8 +36,10 @@ func (mods OrganizationModSlice) Apply(ctx context.Context, n *OrganizationTempl // OrganizationTemplate is an object representing the database table. // all columns are optional and should be set by mods type OrganizationTemplate struct { - ID func() int32 - Name func() null.Val[string] + ID func() int32 + Name func() null.Val[string] + ArcgisID func() null.Val[string] + ArcgisName func() null.Val[string] r organizationR f *Factory @@ -91,6 +93,14 @@ func (o OrganizationTemplate) BuildSetter() *models.OrganizationSetter { val := o.Name() m.Name = omitnull.FromNull(val) } + if o.ArcgisID != nil { + val := o.ArcgisID() + m.ArcgisID = omitnull.FromNull(val) + } + if o.ArcgisName != nil { + val := o.ArcgisName() + m.ArcgisName = omitnull.FromNull(val) + } return m } @@ -119,6 +129,12 @@ func (o OrganizationTemplate) Build() *models.Organization { if o.Name != nil { m.Name = o.Name() } + if o.ArcgisID != nil { + m.ArcgisID = o.ArcgisID() + } + if o.ArcgisName != nil { + m.ArcgisName = o.ArcgisName() + } o.setModelRels(m) @@ -261,6 +277,8 @@ func (m organizationMods) RandomizeAllColumns(f *faker.Faker) OrganizationMod { return OrganizationModSlice{ OrganizationMods.RandomID(f), OrganizationMods.RandomName(f), + OrganizationMods.RandomArcgisID(f), + OrganizationMods.RandomArcgisName(f), } } @@ -348,6 +366,112 @@ func (m organizationMods) RandomNameNotNull(f *faker.Faker) OrganizationMod { }) } +// Set the model columns to this value +func (m organizationMods) ArcgisID(val null.Val[string]) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisID = func() null.Val[string] { return val } + }) +} + +// Set the Column from the function +func (m organizationMods) ArcgisIDFunc(f func() null.Val[string]) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisID = f + }) +} + +// Clear any values for the column +func (m organizationMods) UnsetArcgisID() OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m organizationMods) RandomArcgisID(f *faker.Faker) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisID = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m organizationMods) RandomArcgisIDNotNull(f *faker.Faker) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisID = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m organizationMods) ArcgisName(val null.Val[string]) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisName = func() null.Val[string] { return val } + }) +} + +// Set the Column from the function +func (m organizationMods) ArcgisNameFunc(f func() null.Val[string]) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisName = f + }) +} + +// Clear any values for the column +func (m organizationMods) UnsetArcgisName() OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisName = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m organizationMods) RandomArcgisName(f *faker.Faker) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisName = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m organizationMods) RandomArcgisNameNotNull(f *faker.Faker) OrganizationMod { + return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) { + o.ArcgisName = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + func (m organizationMods) WithParentsCascading() OrganizationMod { return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) { if isDone, _ := organizationWithParentsCascadingCtx.Value(ctx); isDone { diff --git a/main.go b/main.go index 0be40640..77f9c5ac 100644 --- a/main.go +++ b/main.go @@ -76,6 +76,9 @@ func main() { localFS := http.Dir("./static") FileServer(r, "/static", localFS, embeddedStaticFS, "static") + newTokenChannel := make(chan int) + endChannel := make(chan struct{}) + go refreshFieldseekerData(newTokenChannel, endChannel) log.Printf("Serving on %s", bind) log.Fatal(http.ListenAndServe(bind, r)) } diff --git a/migrations/00005_add_arcgis_org.sql b/migrations/00005_add_arcgis_org.sql new file mode 100644 index 00000000..95d9b345 --- /dev/null +++ b/migrations/00005_add_arcgis_org.sql @@ -0,0 +1,10 @@ +-- +goose Up +ALTER TABLE organization ADD COLUMN arcgis_id TEXT; +ALTER TABLE organization ADD COLUMN arcgis_name TEXT; +ALTER TABLE oauth_token ADD COLUMN arcgis_id TEXT; +ALTER TABLE oauth_token ADD COLUMN arcgis_license_type_id TEXT; +-- +goose Down +ALTER TABLE organization DROP COLUMN arcgis_id; +ALTER TABLE organization DROP COLUMN arcgis_name; +ALTER TABLE oauth_token DROP COLUMN arcgis_id; +ALTER TABLE oauth_token DROP COLUMN arcgis_license_type_id; diff --git a/models/oauth_token.bob.go b/models/oauth_token.bob.go index a78f6083..38b582c5 100644 --- a/models/oauth_token.bob.go +++ b/models/oauth_token.bob.go @@ -9,7 +9,9 @@ import ( "io" "time" + "github.com/aarondl/opt/null" "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" "github.com/stephenafamo/bob" "github.com/stephenafamo/bob/dialect/psql" "github.com/stephenafamo/bob/dialect/psql/dialect" @@ -24,12 +26,14 @@ import ( // OauthToken is an object representing the database table. type OauthToken struct { - ID int32 `db:"id,pk" ` - AccessToken string `db:"access_token" ` - Expires time.Time `db:"expires" ` - RefreshToken string `db:"refresh_token" ` - Username string `db:"username" ` - UserID int32 `db:"user_id" ` + ID int32 `db:"id,pk" ` + AccessToken string `db:"access_token" ` + Expires time.Time `db:"expires" ` + RefreshToken string `db:"refresh_token" ` + Username string `db:"username" ` + UserID int32 `db:"user_id" ` + ArcgisID null.Val[string] `db:"arcgis_id" ` + ArcgisLicenseTypeID null.Val[string] `db:"arcgis_license_type_id" ` R oauthTokenR `db:"-" ` } @@ -52,27 +56,31 @@ type oauthTokenR struct { func buildOauthTokenColumns(alias string) oauthTokenColumns { return oauthTokenColumns{ ColumnsExpr: expr.NewColumnsExpr( - "id", "access_token", "expires", "refresh_token", "username", "user_id", + "id", "access_token", "expires", "refresh_token", "username", "user_id", "arcgis_id", "arcgis_license_type_id", ).WithParent("oauth_token"), - tableAlias: alias, - ID: psql.Quote(alias, "id"), - AccessToken: psql.Quote(alias, "access_token"), - Expires: psql.Quote(alias, "expires"), - RefreshToken: psql.Quote(alias, "refresh_token"), - Username: psql.Quote(alias, "username"), - UserID: psql.Quote(alias, "user_id"), + tableAlias: alias, + ID: psql.Quote(alias, "id"), + AccessToken: psql.Quote(alias, "access_token"), + Expires: psql.Quote(alias, "expires"), + RefreshToken: psql.Quote(alias, "refresh_token"), + Username: psql.Quote(alias, "username"), + UserID: psql.Quote(alias, "user_id"), + ArcgisID: psql.Quote(alias, "arcgis_id"), + ArcgisLicenseTypeID: psql.Quote(alias, "arcgis_license_type_id"), } } type oauthTokenColumns struct { expr.ColumnsExpr - tableAlias string - ID psql.Expression - AccessToken psql.Expression - Expires psql.Expression - RefreshToken psql.Expression - Username psql.Expression - UserID psql.Expression + tableAlias string + ID psql.Expression + AccessToken psql.Expression + Expires psql.Expression + RefreshToken psql.Expression + Username psql.Expression + UserID psql.Expression + ArcgisID psql.Expression + ArcgisLicenseTypeID psql.Expression } func (c oauthTokenColumns) Alias() string { @@ -87,16 +95,18 @@ func (oauthTokenColumns) AliasedAs(alias string) oauthTokenColumns { // All values are optional, and do not have to be set // Generated columns are not included type OauthTokenSetter struct { - ID omit.Val[int32] `db:"id,pk" ` - AccessToken omit.Val[string] `db:"access_token" ` - Expires omit.Val[time.Time] `db:"expires" ` - RefreshToken omit.Val[string] `db:"refresh_token" ` - Username omit.Val[string] `db:"username" ` - UserID omit.Val[int32] `db:"user_id" ` + ID omit.Val[int32] `db:"id,pk" ` + AccessToken omit.Val[string] `db:"access_token" ` + Expires omit.Val[time.Time] `db:"expires" ` + RefreshToken omit.Val[string] `db:"refresh_token" ` + Username omit.Val[string] `db:"username" ` + UserID omit.Val[int32] `db:"user_id" ` + ArcgisID omitnull.Val[string] `db:"arcgis_id" ` + ArcgisLicenseTypeID omitnull.Val[string] `db:"arcgis_license_type_id" ` } func (s OauthTokenSetter) SetColumns() []string { - vals := make([]string, 0, 6) + vals := make([]string, 0, 8) if s.ID.IsValue() { vals = append(vals, "id") } @@ -115,6 +125,12 @@ func (s OauthTokenSetter) SetColumns() []string { if s.UserID.IsValue() { vals = append(vals, "user_id") } + if !s.ArcgisID.IsUnset() { + vals = append(vals, "arcgis_id") + } + if !s.ArcgisLicenseTypeID.IsUnset() { + vals = append(vals, "arcgis_license_type_id") + } return vals } @@ -137,6 +153,12 @@ func (s OauthTokenSetter) Overwrite(t *OauthToken) { if s.UserID.IsValue() { t.UserID = s.UserID.MustGet() } + if !s.ArcgisID.IsUnset() { + t.ArcgisID = s.ArcgisID.MustGetNull() + } + if !s.ArcgisLicenseTypeID.IsUnset() { + t.ArcgisLicenseTypeID = s.ArcgisLicenseTypeID.MustGetNull() + } } func (s *OauthTokenSetter) Apply(q *dialect.InsertQuery) { @@ -145,7 +167,7 @@ func (s *OauthTokenSetter) Apply(q *dialect.InsertQuery) { }) q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) { - vals := make([]bob.Expression, 6) + vals := make([]bob.Expression, 8) if s.ID.IsValue() { vals[0] = psql.Arg(s.ID.MustGet()) } else { @@ -182,6 +204,18 @@ func (s *OauthTokenSetter) Apply(q *dialect.InsertQuery) { vals[5] = psql.Raw("DEFAULT") } + if !s.ArcgisID.IsUnset() { + vals[6] = psql.Arg(s.ArcgisID.MustGetNull()) + } else { + vals[6] = psql.Raw("DEFAULT") + } + + if !s.ArcgisLicenseTypeID.IsUnset() { + vals[7] = psql.Arg(s.ArcgisLicenseTypeID.MustGetNull()) + } else { + vals[7] = psql.Raw("DEFAULT") + } + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") })) } @@ -191,7 +225,7 @@ func (s OauthTokenSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { } func (s OauthTokenSetter) Expressions(prefix ...string) []bob.Expression { - exprs := make([]bob.Expression, 0, 6) + exprs := make([]bob.Expression, 0, 8) if s.ID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ @@ -235,6 +269,20 @@ func (s OauthTokenSetter) Expressions(prefix ...string) []bob.Expression { }}) } + if !s.ArcgisID.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "arcgis_id")...), + psql.Arg(s.ArcgisID), + }}) + } + + if !s.ArcgisLicenseTypeID.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "arcgis_license_type_id")...), + psql.Arg(s.ArcgisLicenseTypeID), + }}) + } + return exprs } @@ -534,12 +582,14 @@ func (oauthToken0 *OauthToken) AttachUserUser(ctx context.Context, exec bob.Exec } type oauthTokenWhere[Q psql.Filterable] struct { - ID psql.WhereMod[Q, int32] - AccessToken psql.WhereMod[Q, string] - Expires psql.WhereMod[Q, time.Time] - RefreshToken psql.WhereMod[Q, string] - Username psql.WhereMod[Q, string] - UserID psql.WhereMod[Q, int32] + ID psql.WhereMod[Q, int32] + AccessToken psql.WhereMod[Q, string] + Expires psql.WhereMod[Q, time.Time] + RefreshToken psql.WhereMod[Q, string] + Username psql.WhereMod[Q, string] + UserID psql.WhereMod[Q, int32] + ArcgisID psql.WhereNullMod[Q, string] + ArcgisLicenseTypeID psql.WhereNullMod[Q, string] } func (oauthTokenWhere[Q]) AliasedAs(alias string) oauthTokenWhere[Q] { @@ -548,12 +598,14 @@ func (oauthTokenWhere[Q]) AliasedAs(alias string) oauthTokenWhere[Q] { func buildOauthTokenWhere[Q psql.Filterable](cols oauthTokenColumns) oauthTokenWhere[Q] { return oauthTokenWhere[Q]{ - ID: psql.Where[Q, int32](cols.ID), - AccessToken: psql.Where[Q, string](cols.AccessToken), - Expires: psql.Where[Q, time.Time](cols.Expires), - RefreshToken: psql.Where[Q, string](cols.RefreshToken), - Username: psql.Where[Q, string](cols.Username), - UserID: psql.Where[Q, int32](cols.UserID), + ID: psql.Where[Q, int32](cols.ID), + AccessToken: psql.Where[Q, string](cols.AccessToken), + Expires: psql.Where[Q, time.Time](cols.Expires), + RefreshToken: psql.Where[Q, string](cols.RefreshToken), + Username: psql.Where[Q, string](cols.Username), + UserID: psql.Where[Q, int32](cols.UserID), + ArcgisID: psql.WhereNull[Q, string](cols.ArcgisID), + ArcgisLicenseTypeID: psql.WhereNull[Q, string](cols.ArcgisLicenseTypeID), } } diff --git a/models/organization.bob.go b/models/organization.bob.go index 485fdff8..7f870959 100644 --- a/models/organization.bob.go +++ b/models/organization.bob.go @@ -25,8 +25,10 @@ import ( // Organization is an object representing the database table. type Organization struct { - ID int32 `db:"id,pk" ` - Name null.Val[string] `db:"name" ` + ID int32 `db:"id,pk" ` + Name null.Val[string] `db:"name" ` + ArcgisID null.Val[string] `db:"arcgis_id" ` + ArcgisName null.Val[string] `db:"arcgis_name" ` R organizationR `db:"-" ` } @@ -49,11 +51,13 @@ type organizationR struct { func buildOrganizationColumns(alias string) organizationColumns { return organizationColumns{ ColumnsExpr: expr.NewColumnsExpr( - "id", "name", + "id", "name", "arcgis_id", "arcgis_name", ).WithParent("organization"), tableAlias: alias, ID: psql.Quote(alias, "id"), Name: psql.Quote(alias, "name"), + ArcgisID: psql.Quote(alias, "arcgis_id"), + ArcgisName: psql.Quote(alias, "arcgis_name"), } } @@ -62,6 +66,8 @@ type organizationColumns struct { tableAlias string ID psql.Expression Name psql.Expression + ArcgisID psql.Expression + ArcgisName psql.Expression } func (c organizationColumns) Alias() string { @@ -76,18 +82,26 @@ func (organizationColumns) AliasedAs(alias string) organizationColumns { // All values are optional, and do not have to be set // Generated columns are not included type OrganizationSetter struct { - ID omit.Val[int32] `db:"id,pk" ` - Name omitnull.Val[string] `db:"name" ` + ID omit.Val[int32] `db:"id,pk" ` + Name omitnull.Val[string] `db:"name" ` + ArcgisID omitnull.Val[string] `db:"arcgis_id" ` + ArcgisName omitnull.Val[string] `db:"arcgis_name" ` } func (s OrganizationSetter) SetColumns() []string { - vals := make([]string, 0, 2) + vals := make([]string, 0, 4) if s.ID.IsValue() { vals = append(vals, "id") } if !s.Name.IsUnset() { vals = append(vals, "name") } + if !s.ArcgisID.IsUnset() { + vals = append(vals, "arcgis_id") + } + if !s.ArcgisName.IsUnset() { + vals = append(vals, "arcgis_name") + } return vals } @@ -98,6 +112,12 @@ func (s OrganizationSetter) Overwrite(t *Organization) { if !s.Name.IsUnset() { t.Name = s.Name.MustGetNull() } + if !s.ArcgisID.IsUnset() { + t.ArcgisID = s.ArcgisID.MustGetNull() + } + if !s.ArcgisName.IsUnset() { + t.ArcgisName = s.ArcgisName.MustGetNull() + } } func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { @@ -106,7 +126,7 @@ func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { }) q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) { - vals := make([]bob.Expression, 2) + vals := make([]bob.Expression, 4) if s.ID.IsValue() { vals[0] = psql.Arg(s.ID.MustGet()) } else { @@ -119,6 +139,18 @@ func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { vals[1] = psql.Raw("DEFAULT") } + if !s.ArcgisID.IsUnset() { + vals[2] = psql.Arg(s.ArcgisID.MustGetNull()) + } else { + vals[2] = psql.Raw("DEFAULT") + } + + if !s.ArcgisName.IsUnset() { + vals[3] = psql.Arg(s.ArcgisName.MustGetNull()) + } else { + vals[3] = psql.Raw("DEFAULT") + } + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") })) } @@ -128,7 +160,7 @@ func (s OrganizationSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { } func (s OrganizationSetter) Expressions(prefix ...string) []bob.Expression { - exprs := make([]bob.Expression, 0, 2) + exprs := make([]bob.Expression, 0, 4) if s.ID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ @@ -144,6 +176,20 @@ func (s OrganizationSetter) Expressions(prefix ...string) []bob.Expression { }}) } + if !s.ArcgisID.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "arcgis_id")...), + psql.Arg(s.ArcgisID), + }}) + } + + if !s.ArcgisName.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "arcgis_name")...), + psql.Arg(s.ArcgisName), + }}) + } + return exprs } @@ -463,8 +509,10 @@ func (organization0 *Organization) AttachUser(ctx context.Context, exec bob.Exec } type organizationWhere[Q psql.Filterable] struct { - ID psql.WhereMod[Q, int32] - Name psql.WhereNullMod[Q, string] + ID psql.WhereMod[Q, int32] + Name psql.WhereNullMod[Q, string] + ArcgisID psql.WhereNullMod[Q, string] + ArcgisName psql.WhereNullMod[Q, string] } func (organizationWhere[Q]) AliasedAs(alias string) organizationWhere[Q] { @@ -473,8 +521,10 @@ func (organizationWhere[Q]) AliasedAs(alias string) organizationWhere[Q] { func buildOrganizationWhere[Q psql.Filterable](cols organizationColumns) organizationWhere[Q] { return organizationWhere[Q]{ - ID: psql.Where[Q, int32](cols.ID), - Name: psql.WhereNull[Q, string](cols.Name), + ID: psql.Where[Q, int32](cols.ID), + Name: psql.WhereNull[Q, string](cols.Name), + ArcgisID: psql.WhereNull[Q, string](cols.ArcgisID), + ArcgisName: psql.WhereNull[Q, string](cols.ArcgisName), } } diff --git a/sql/oauth_by_user_id.bob.go b/sql/oauth_by_user_id.bob.go index 81932e6a..590ac15b 100644 --- a/sql/oauth_by_user_id.bob.go +++ b/sql/oauth_by_user_id.bob.go @@ -10,6 +10,7 @@ import ( "iter" "time" + "github.com/aarondl/opt/null" "github.com/stephenafamo/bob" "github.com/stephenafamo/bob/dialect/psql" "github.com/stephenafamo/bob/dialect/psql/dialect" @@ -20,7 +21,7 @@ import ( //go:embed oauth_by_user_id.bob.sql var formattedQueries_oauth_by_user_id string -var oauthTokenByUserIdSQL = formattedQueries_oauth_by_user_id[156:440] +var oauthTokenByUserIdSQL = formattedQueries_oauth_by_user_id[156:550] type OauthTokenByUserIdQuery = orm.ModQuery[*dialect.SelectQuery, oauthTokenByUserId, OauthTokenByUserIdRow, []OauthTokenByUserIdRow, oauthTokenByUserIdTransformer] @@ -47,6 +48,8 @@ func OauthTokenByUserId(UserID int32) *OauthTokenByUserIdQuery { row.ScheduleScanByIndex(3, &t.RefreshToken) row.ScheduleScanByIndex(4, &t.Username) row.ScheduleScanByIndex(5, &t.UserID) + row.ScheduleScanByIndex(6, &t.ArcgisID) + row.ScheduleScanByIndex(7, &t.ArcgisLicenseTypeID) return &t, nil }, func(v any) (OauthTokenByUserIdRow, error) { return *(v.(*OauthTokenByUserIdRow)), nil @@ -54,20 +57,22 @@ func OauthTokenByUserId(UserID int32) *OauthTokenByUserIdQuery { }, }, Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) { - q.AppendSelect(expressionTypArgs.subExpr(7, 247)) - q.SetTable(expressionTypArgs.subExpr(253, 264)) - q.AppendWhere(expressionTypArgs.subExpr(272, 284)) + q.AppendSelect(expressionTypArgs.subExpr(7, 357)) + q.SetTable(expressionTypArgs.subExpr(363, 374)) + q.AppendWhere(expressionTypArgs.subExpr(382, 394)) }), } } type OauthTokenByUserIdRow = struct { - ID int32 `db:"id"` - AccessToken string `db:"access_token"` - Expires time.Time `db:"expires"` - RefreshToken string `db:"refresh_token"` - Username string `db:"username"` - UserID int32 `db:"user_id"` + ID int32 `db:"id"` + AccessToken string `db:"access_token"` + Expires time.Time `db:"expires"` + RefreshToken string `db:"refresh_token"` + Username string `db:"username"` + UserID int32 `db:"user_id"` + ArcgisID null.Val[string] `db:"arcgis_id"` + ArcgisLicenseTypeID null.Val[string] `db:"arcgis_license_type_id"` } type oauthTokenByUserIdTransformer = bob.SliceTransformer[OauthTokenByUserIdRow, []OauthTokenByUserIdRow] @@ -80,8 +85,8 @@ func (o oauthTokenByUserId) args() iter.Seq[orm.ArgWithPosition] { return func(yield func(arg orm.ArgWithPosition) bool) { if !yield(orm.ArgWithPosition{ Name: "userID", - Start: 282, - Stop: 284, + Start: 392, + Stop: 394, Expression: o.UserID, }) { return diff --git a/sql/oauth_by_user_id.bob.sql b/sql/oauth_by_user_id.bob.sql index cb0f6380..4d372c2b 100644 --- a/sql/oauth_by_user_id.bob.sql +++ b/sql/oauth_by_user_id.bob.sql @@ -2,5 +2,5 @@ -- This file is meant to be re-generated in place and/or deleted at any time. -- OauthTokenByUserId -SELECT "oauth_token"."id" AS "id", "oauth_token"."access_token" AS "access_token", "oauth_token"."expires" AS "expires", "oauth_token"."refresh_token" AS "refresh_token", "oauth_token"."username" AS "username", "oauth_token"."user_id" AS "user_id" FROM oauth_token WHERE +SELECT "oauth_token"."id" AS "id", "oauth_token"."access_token" AS "access_token", "oauth_token"."expires" AS "expires", "oauth_token"."refresh_token" AS "refresh_token", "oauth_token"."username" AS "username", "oauth_token"."user_id" AS "user_id", "oauth_token"."arcgis_id" AS "arcgis_id", "oauth_token"."arcgis_license_type_id" AS "arcgis_license_type_id" FROM oauth_token WHERE user_id = $1; diff --git a/sql/oauth_by_user_id.bob_test.go b/sql/oauth_by_user_id.bob_test.go index 4a610d1a..cf3425ce 100644 --- a/sql/oauth_by_user_id.bob_test.go +++ b/sql/oauth_by_user_id.bob_test.go @@ -84,8 +84,8 @@ func TestOauthTokenByUserId(t *testing.T) { t.Fatal(err) } - if len(columns) != 6 { - t.Fatalf("expected %d columns, got %d", 6, len(columns)) + if len(columns) != 8 { + t.Fatalf("expected %d columns, got %d", 8, len(columns)) } if columns[0] != "id" { @@ -111,5 +111,13 @@ func TestOauthTokenByUserId(t *testing.T) { if columns[5] != "user_id" { t.Fatalf("expected column %d to be %s, got %s", 5, "user_id", columns[5]) } + + if columns[6] != "arcgis_id" { + t.Fatalf("expected column %d to be %s, got %s", 6, "arcgis_id", columns[6]) + } + + if columns[7] != "arcgis_license_type_id" { + t.Fatalf("expected column %d to be %s, got %s", 7, "arcgis_license_type_id", columns[7]) + } }) } diff --git a/sql/update_oauth_org.bob.go b/sql/update_oauth_org.bob.go new file mode 100644 index 00000000..7e794bc8 --- /dev/null +++ b/sql/update_oauth_org.bob.go @@ -0,0 +1,95 @@ +// Code generated by BobGen psql v0.41.1. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package sql + +import ( + "context" + _ "embed" + "io" + "iter" + + "github.com/stephenafamo/bob" + "github.com/stephenafamo/bob/dialect/psql" + "github.com/stephenafamo/bob/dialect/psql/dialect" + "github.com/stephenafamo/bob/orm" +) + +//go:embed update_oauth_org.bob.sql +var formattedQueries_update_oauth_org string + +var updateOauthTokenOrgSQL = formattedQueries_update_oauth_org[157:249] + +type UpdateOauthTokenOrgQuery = orm.ModExecQuery[*dialect.UpdateQuery, updateOauthTokenOrg] + +func UpdateOauthTokenOrg(ArcgisID string, ArcgisLicenseTypeID string, RefreshToken string) *UpdateOauthTokenOrgQuery { + var expressionTypArgs updateOauthTokenOrg + + expressionTypArgs.ArcgisID = psql.Arg(ArcgisID) + expressionTypArgs.ArcgisLicenseTypeID = psql.Arg(ArcgisLicenseTypeID) + expressionTypArgs.RefreshToken = psql.Arg(RefreshToken) + + return &UpdateOauthTokenOrgQuery{ + ExecQuery: orm.ExecQuery[updateOauthTokenOrg]{ + BaseQuery: bob.BaseQuery[updateOauthTokenOrg]{ + Expression: expressionTypArgs, + Dialect: dialect.Dialect, + QueryType: bob.QueryTypeUpdate, + }, + }, + Mod: bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) { + q.Table.Expression = expressionTypArgs.subExpr(7, 18) + q.AppendSet(expressionTypArgs.subExpr(23, 66)) + q.AppendWhere(expressionTypArgs.subExpr(74, 92)) + }), + } +} + +type updateOauthTokenOrg struct { + ArcgisID bob.Expression + ArcgisLicenseTypeID bob.Expression + RefreshToken bob.Expression +} + +func (o updateOauthTokenOrg) args() iter.Seq[orm.ArgWithPosition] { + return func(yield func(arg orm.ArgWithPosition) bool) { + if !yield(orm.ArgWithPosition{ + Name: "arcgisID", + Start: 35, + Stop: 37, + Expression: o.ArcgisID, + }) { + return + } + + if !yield(orm.ArgWithPosition{ + Name: "arcgisLicenseTypeID", + Start: 64, + Stop: 66, + Expression: o.ArcgisLicenseTypeID, + }) { + return + } + + if !yield(orm.ArgWithPosition{ + Name: "refreshToken", + Start: 90, + Stop: 92, + Expression: o.RefreshToken, + }) { + return + } + } +} + +func (o updateOauthTokenOrg) raw(from, to int) string { + return updateOauthTokenOrgSQL[from:to] +} + +func (o updateOauthTokenOrg) subExpr(from, to int) bob.Expression { + return orm.ArgsToExpression(updateOauthTokenOrgSQL, from, to, o.args()) +} + +func (o updateOauthTokenOrg) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) { + return o.subExpr(0, len(updateOauthTokenOrgSQL)).WriteSQL(ctx, w, d, start) +} diff --git a/sql/update_oauth_org.bob.sql b/sql/update_oauth_org.bob.sql new file mode 100644 index 00000000..965228ee --- /dev/null +++ b/sql/update_oauth_org.bob.sql @@ -0,0 +1,6 @@ +-- Code generated by BobGen psql v0.41.1. DO NOT EDIT. +-- This file is meant to be re-generated in place and/or deleted at any time. + +-- UpdateOauthTokenOrg +UPDATE oauth_token SET arcgis_id = $1, arcgis_license_type_id = $2 + WHERE refresh_token = $3; diff --git a/sql/update_oauth_org.bob_test.go b/sql/update_oauth_org.bob_test.go new file mode 100644 index 00000000..b79c7afe --- /dev/null +++ b/sql/update_oauth_org.bob_test.go @@ -0,0 +1,76 @@ +// Code generated by BobGen psql v0.41.1. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package sql + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stephenafamo/bob" + "github.com/stephenafamo/bob/dialect/psql" + testutils "github.com/stephenafamo/bob/test/utils" +) + +func TestUpdateOauthTokenOrg(t *testing.T) { + t.Run("Base", func(t *testing.T) { + var sb strings.Builder + + query := UpdateOauthTokenOrg(random_string(nil), random_string(nil), random_string(nil)) + + if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil { + t.Fatal(err) + } + + if diff := cmp.Diff(updateOauthTokenOrgSQL, sb.String()); diff != "" { + t.Fatalf("unexpected result (-got +want):\n%s", diff) + } + }) + + t.Run("Mod", func(t *testing.T) { + var sb strings.Builder + + query := UpdateOauthTokenOrg(random_string(nil), random_string(nil), random_string(nil)) + + if _, err := psql.Update(query).WriteQuery(t.Context(), &sb, 1); err != nil { + t.Fatal(err) + } + + queryDiff, err := testutils.QueryDiff(updateOauthTokenOrgSQL, sb.String(), formatQuery) + if err != nil { + t.Fatal(err) + } + if queryDiff != "" { + fmt.Println(sb.String()) + t.Fatalf("unexpected result (-got +want):\n%s", queryDiff) + } + }) + + t.Run("Exec", func(t *testing.T) { + if testDB == nil { + t.Skip("skipping test, no DSN provided") + } + + ctxTx, cancel := context.WithCancel(t.Context()) + defer cancel() + + tx, err := testDB.Begin(ctxTx) + if err != nil { + t.Fatalf("Error starting transaction: %v", err) + } + + defer func() { + if err := tx.Rollback(ctxTx); err != nil { + t.Fatalf("Error rolling back transaction: %v", err) + } + }() + + query := psql.Update(UpdateOauthTokenOrg(random_string(nil), random_string(nil), random_string(nil))) + if _, err := bob.Exec(ctxTx, tx, query); err != nil { + t.Fatal(err) + } + }) +} diff --git a/sql/update_oauth_org.sql b/sql/update_oauth_org.sql new file mode 100644 index 00000000..db26f4f4 --- /dev/null +++ b/sql/update_oauth_org.sql @@ -0,0 +1,3 @@ +-- UpdateOauthTokenOrg +UPDATE oauth_token SET arcgis_id = $1, arcgis_license_type_id = $2 + WHERE refresh_token = $3;