diff --git a/arcgis/oauth.go b/arcgis/oauth.go new file mode 100644 index 00000000..57b20298 --- /dev/null +++ b/arcgis/oauth.go @@ -0,0 +1,15 @@ +package arcgis + +import ( + "context" + + "github.com/Gleipnir-Technology/bob/dialect/psql/sm" + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/models" +) + +func GetOAuthForUser(ctx context.Context, user *models.User) (*models.OauthToken, error) { + return user.UserOauthTokens( + sm.OrderBy("created").Desc(), + ).One(ctx, db.PGInstance.BobDB) +} diff --git a/background/arcgis.go b/background/arcgis.go index e103ed56..b2f26159 100644 --- a/background/arcgis.go +++ b/background/arcgis.go @@ -110,6 +110,7 @@ func HandleOauthAccessCode(ctx context.Context, user *models.User, code string) AccessTokenExpires: omit.From(accessExpires), ArcgisID: omitnull.FromPtr[string](nil), ArcgisLicenseTypeID: omitnull.FromPtr[string](nil), + Created: omit.From(time.Now()), InvalidatedAt: omitnull.FromPtr[time.Time](nil), RefreshToken: omit.From(token.RefreshToken), RefreshTokenExpires: omit.From(refreshExpires), diff --git a/db/dbinfo/oauth_token.bob.go b/db/dbinfo/oauth_token.bob.go index 3101f04e..2b7ab0aa 100644 --- a/db/dbinfo/oauth_token.bob.go +++ b/db/dbinfo/oauth_token.bob.go @@ -105,6 +105,15 @@ var OauthTokens = Table[ Generated: false, AutoIncr: false, }, + Created: column{ + Name: "created", + DBType: "timestamp without time zone", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, }, Indexes: oauthTokenIndexes{ OauthTokenPkey: index{ @@ -156,11 +165,12 @@ type oauthTokenColumns struct { ArcgisLicenseTypeID column RefreshTokenExpires column InvalidatedAt column + Created column } func (c oauthTokenColumns) AsSlice() []column { return []column{ - c.ID, c.AccessToken, c.AccessTokenExpires, c.RefreshToken, c.Username, c.UserID, c.ArcgisID, c.ArcgisLicenseTypeID, c.RefreshTokenExpires, c.InvalidatedAt, + c.ID, c.AccessToken, c.AccessTokenExpires, c.RefreshToken, c.Username, c.UserID, c.ArcgisID, c.ArcgisLicenseTypeID, c.RefreshTokenExpires, c.InvalidatedAt, c.Created, } } diff --git a/db/factory/bobfactory_main.bob.go b/db/factory/bobfactory_main.bob.go index b60f1155..2238ff2e 100644 --- a/db/factory/bobfactory_main.bob.go +++ b/db/factory/bobfactory_main.bob.go @@ -2912,6 +2912,7 @@ func (f *Factory) FromExistingOauthToken(m *models.OauthToken) *OauthTokenTempla o.ArcgisLicenseTypeID = func() null.Val[string] { return m.ArcgisLicenseTypeID } o.RefreshTokenExpires = func() time.Time { return m.RefreshTokenExpires } o.InvalidatedAt = func() null.Val[time.Time] { return m.InvalidatedAt } + o.Created = func() time.Time { return m.Created } ctx := context.Background() if m.R.UserUser != nil { diff --git a/db/factory/oauth_token.bob.go b/db/factory/oauth_token.bob.go index 8bb6fe31..d143a268 100644 --- a/db/factory/oauth_token.bob.go +++ b/db/factory/oauth_token.bob.go @@ -47,6 +47,7 @@ type OauthTokenTemplate struct { ArcgisLicenseTypeID func() null.Val[string] RefreshTokenExpires func() time.Time InvalidatedAt func() null.Val[time.Time] + Created func() time.Time r oauthTokenR f *Factory @@ -125,6 +126,10 @@ func (o OauthTokenTemplate) BuildSetter() *models.OauthTokenSetter { val := o.InvalidatedAt() m.InvalidatedAt = omitnull.FromNull(val) } + if o.Created != nil { + val := o.Created() + m.Created = omit.From(val) + } return m } @@ -177,6 +182,9 @@ func (o OauthTokenTemplate) Build() *models.OauthToken { if o.InvalidatedAt != nil { m.InvalidatedAt = o.InvalidatedAt() } + if o.Created != nil { + m.Created = o.Created() + } o.setModelRels(m) @@ -217,6 +225,10 @@ func ensureCreatableOauthToken(m *models.OauthTokenSetter) { val := random_int32(nil) m.UserID = omit.From(val) } + if !(m.Created.IsValue()) { + val := random_time_Time(nil) + m.Created = omit.From(val) + } } // insertOptRels creates and inserts any optional the relationships on *models.OauthToken @@ -346,6 +358,7 @@ func (m oauthTokenMods) RandomizeAllColumns(f *faker.Faker) OauthTokenMod { OauthTokenMods.RandomArcgisLicenseTypeID(f), OauthTokenMods.RandomRefreshTokenExpires(f), OauthTokenMods.RandomInvalidatedAt(f), + OauthTokenMods.RandomCreated(f), } } @@ -725,6 +738,37 @@ func (m oauthTokenMods) RandomInvalidatedAtNotNull(f *faker.Faker) OauthTokenMod }) } +// Set the model columns to this value +func (m oauthTokenMods) Created(val time.Time) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.Created = func() time.Time { return val } + }) +} + +// Set the Column from the function +func (m oauthTokenMods) CreatedFunc(f func() time.Time) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.Created = f + }) +} + +// Clear any values for the column +func (m oauthTokenMods) UnsetCreated() OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.Created = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m oauthTokenMods) RandomCreated(f *faker.Faker) OauthTokenMod { + return OauthTokenModFunc(func(_ context.Context, o *OauthTokenTemplate) { + o.Created = func() time.Time { + return random_time_Time(f) + } + }) +} + func (m oauthTokenMods) WithParentsCascading() OauthTokenMod { return OauthTokenModFunc(func(ctx context.Context, o *OauthTokenTemplate) { if isDone, _ := oauthTokenWithParentsCascadingCtx.Value(ctx); isDone { diff --git a/db/migrations/00061_oauth_token_created.sql b/db/migrations/00061_oauth_token_created.sql new file mode 100644 index 00000000..65317e07 --- /dev/null +++ b/db/migrations/00061_oauth_token_created.sql @@ -0,0 +1,6 @@ +-- +goose Up +ALTER TABLE oauth_token ADD COLUMN created TIMESTAMP WITHOUT TIME ZONE; +UPDATE oauth_token SET created = now(); +ALTER TABLE oauth_token ALTER COLUMN created SET NOT NULL; +-- +goose Down +ALTER TABLE oauth_token DROP COLUMN created; diff --git a/db/models/oauth_token.bob.go b/db/models/oauth_token.bob.go index 8d8efe52..c19ef982 100644 --- a/db/models/oauth_token.bob.go +++ b/db/models/oauth_token.bob.go @@ -36,6 +36,7 @@ type OauthToken struct { ArcgisLicenseTypeID null.Val[string] `db:"arcgis_license_type_id" ` RefreshTokenExpires time.Time `db:"refresh_token_expires" ` InvalidatedAt null.Val[time.Time] `db:"invalidated_at" ` + Created time.Time `db:"created" ` R oauthTokenR `db:"-" ` } @@ -58,7 +59,7 @@ type oauthTokenR struct { func buildOauthTokenColumns(alias string) oauthTokenColumns { return oauthTokenColumns{ ColumnsExpr: expr.NewColumnsExpr( - "id", "access_token", "access_token_expires", "refresh_token", "username", "user_id", "arcgis_id", "arcgis_license_type_id", "refresh_token_expires", "invalidated_at", + "id", "access_token", "access_token_expires", "refresh_token", "username", "user_id", "arcgis_id", "arcgis_license_type_id", "refresh_token_expires", "invalidated_at", "created", ).WithParent("oauth_token"), tableAlias: alias, ID: psql.Quote(alias, "id"), @@ -71,6 +72,7 @@ func buildOauthTokenColumns(alias string) oauthTokenColumns { ArcgisLicenseTypeID: psql.Quote(alias, "arcgis_license_type_id"), RefreshTokenExpires: psql.Quote(alias, "refresh_token_expires"), InvalidatedAt: psql.Quote(alias, "invalidated_at"), + Created: psql.Quote(alias, "created"), } } @@ -87,6 +89,7 @@ type oauthTokenColumns struct { ArcgisLicenseTypeID psql.Expression RefreshTokenExpires psql.Expression InvalidatedAt psql.Expression + Created psql.Expression } func (c oauthTokenColumns) Alias() string { @@ -111,10 +114,11 @@ type OauthTokenSetter struct { ArcgisLicenseTypeID omitnull.Val[string] `db:"arcgis_license_type_id" ` RefreshTokenExpires omit.Val[time.Time] `db:"refresh_token_expires" ` InvalidatedAt omitnull.Val[time.Time] `db:"invalidated_at" ` + Created omit.Val[time.Time] `db:"created" ` } func (s OauthTokenSetter) SetColumns() []string { - vals := make([]string, 0, 10) + vals := make([]string, 0, 11) if s.ID.IsValue() { vals = append(vals, "id") } @@ -145,6 +149,9 @@ func (s OauthTokenSetter) SetColumns() []string { if !s.InvalidatedAt.IsUnset() { vals = append(vals, "invalidated_at") } + if s.Created.IsValue() { + vals = append(vals, "created") + } return vals } @@ -179,6 +186,9 @@ func (s OauthTokenSetter) Overwrite(t *OauthToken) { if !s.InvalidatedAt.IsUnset() { t.InvalidatedAt = s.InvalidatedAt.MustGetNull() } + if s.Created.IsValue() { + t.Created = s.Created.MustGet() + } } func (s *OauthTokenSetter) Apply(q *dialect.InsertQuery) { @@ -187,7 +197,7 @@ func (s *OauthTokenSetter) Apply(q *dialect.InsertQuery) { }) q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { - vals := make([]bob.Expression, 10) + vals := make([]bob.Expression, 11) if s.ID.IsValue() { vals[0] = psql.Arg(s.ID.MustGet()) } else { @@ -248,6 +258,12 @@ func (s *OauthTokenSetter) Apply(q *dialect.InsertQuery) { vals[9] = psql.Raw("DEFAULT") } + if s.Created.IsValue() { + vals[10] = psql.Arg(s.Created.MustGet()) + } else { + vals[10] = psql.Raw("DEFAULT") + } + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") })) } @@ -257,7 +273,7 @@ func (s OauthTokenSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { } func (s OauthTokenSetter) Expressions(prefix ...string) []bob.Expression { - exprs := make([]bob.Expression, 0, 10) + exprs := make([]bob.Expression, 0, 11) if s.ID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ @@ -329,6 +345,13 @@ func (s OauthTokenSetter) Expressions(prefix ...string) []bob.Expression { }}) } + if s.Created.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "created")...), + psql.Arg(s.Created), + }}) + } + return exprs } @@ -638,6 +661,7 @@ type oauthTokenWhere[Q psql.Filterable] struct { ArcgisLicenseTypeID psql.WhereNullMod[Q, string] RefreshTokenExpires psql.WhereMod[Q, time.Time] InvalidatedAt psql.WhereNullMod[Q, time.Time] + Created psql.WhereMod[Q, time.Time] } func (oauthTokenWhere[Q]) AliasedAs(alias string) oauthTokenWhere[Q] { @@ -656,6 +680,7 @@ func buildOauthTokenWhere[Q psql.Filterable](cols oauthTokenColumns) oauthTokenW ArcgisLicenseTypeID: psql.WhereNull[Q, string](cols.ArcgisLicenseTypeID), RefreshTokenExpires: psql.Where[Q, time.Time](cols.RefreshTokenExpires), InvalidatedAt: psql.WhereNull[Q, time.Time](cols.InvalidatedAt), + Created: psql.Where[Q, time.Time](cols.Created), } } diff --git a/html/template/sync/setting-integration.html b/html/template/sync/setting-integration.html index 2afbc271..8ce34735 100644 --- a/html/template/sync/setting-integration.html +++ b/html/template/sync/setting-integration.html @@ -1,6 +1,6 @@ -{{ template "sync/layout/base.html" . }} +{{ template "sync/layout/authenticated.html" . }} -{{ define "title" }}Dash{{ end }} +{{ define "title" }}Settings - Integrations{{ end }} {{ define "extraheader" }}