diff --git a/message/cache_postgres.go b/message/cache_postgres.go index 0a57d18e..ce0551c9 100644 --- a/message/cache_postgres.go +++ b/message/cache_postgres.go @@ -103,7 +103,7 @@ var pgQueries = queries{ // NewPostgresStore creates a new PostgreSQL-backed message cache store using an existing database connection pool. func NewPostgresStore(db *sql.DB, batchSize int, batchTimeout time.Duration) (*Cache, error) { - if err := setupPostgresDB(db); err != nil { + if err := setupPostgres(db); err != nil { return nil, err } return newCache(db, pgQueries, nil, batchSize, batchTimeout, false), nil diff --git a/message/cache_postgres_schema.go b/message/cache_postgres_schema.go index a647cdf9..4b5730a0 100644 --- a/message/cache_postgres_schema.go +++ b/message/cache_postgres_schema.go @@ -60,7 +60,7 @@ const ( postgresSelectSchemaVersionQuery = `SELECT version FROM schema_version WHERE store = 'message'` ) -func setupPostgresDB(db *sql.DB) error { +func setupPostgres(db *sql.DB) error { var schemaVersion int err := db.QueryRow(postgresSelectSchemaVersionQuery).Scan(&schemaVersion) if err != nil { diff --git a/user/manager.go b/user/manager.go index a8e8dba3..a1412be3 100644 --- a/user/manager.go +++ b/user/manager.go @@ -57,19 +57,25 @@ type Manager struct { var _ Auther = (*Manager)(nil) -// initManager sets defaults and runs startup tasks common to all backends -func initManager(manager *Manager) error { - if manager.config.BcryptCost <= 0 { - manager.config.BcryptCost = DefaultUserPasswordBcryptCost +func newManager(db *sql.DB, queries queries, config *Config) (*Manager, error) { + if config.BcryptCost <= 0 { + config.BcryptCost = DefaultUserPasswordBcryptCost } - if manager.config.QueueWriterInterval.Seconds() <= 0 { - manager.config.QueueWriterInterval = DefaultUserStatsQueueWriterInterval + if config.QueueWriterInterval.Seconds() <= 0 { + config.QueueWriterInterval = DefaultUserStatsQueueWriterInterval + } + manager := &Manager{ + config: config, + db: db, + statsQueue: make(map[string]*Stats), + tokenQueue: make(map[string]*TokenUpdate), + queries: queries, } if err := manager.maybeProvisionUsersAccessAndTokens(); err != nil { - return err + return nil, err } go manager.asyncQueueWriter(manager.config.QueueWriterInterval) - return nil + return manager, nil } // Authenticate checks username and password and returns a User if correct, and the user has not been diff --git a/user/manager_postgres.go b/user/manager_postgres.go index b7ef2d08..bc8e3852 100644 --- a/user/manager_postgres.go +++ b/user/manager_postgres.go @@ -204,85 +204,67 @@ const ( ) // NewPostgresManager creates a new Manager backed by a PostgreSQL database using an existing connection pool. +var postgresQueries = queries{ + selectUserByID: postgresSelectUserByIDQuery, + selectUserByName: postgresSelectUserByNameQuery, + selectUserByToken: postgresSelectUserByTokenQuery, + selectUserByStripeCustomerID: postgresSelectUserByStripeCustomerIDQuery, + selectUsernames: postgresSelectUsernamesQuery, + selectUserCount: postgresSelectUserCountQuery, + selectUserIDFromUsername: postgresSelectUserIDFromUsernameQuery, + insertUser: postgresInsertUserQuery, + updateUserPass: postgresUpdateUserPassQuery, + updateUserRole: postgresUpdateUserRoleQuery, + updateUserProvisioned: postgresUpdateUserProvisionedQuery, + updateUserPrefs: postgresUpdateUserPrefsQuery, + updateUserStats: postgresUpdateUserStatsQuery, + updateUserStatsResetAll: postgresUpdateUserStatsResetAllQuery, + updateUserTier: postgresUpdateUserTierQuery, + updateUserDeleted: postgresUpdateUserDeletedQuery, + deleteUser: postgresDeleteUserQuery, + deleteUserTier: postgresDeleteUserTierQuery, + deleteUsersMarked: postgresDeleteUsersMarkedQuery, + selectTopicPerms: postgresSelectTopicPermsQuery, + selectUserAllAccess: postgresSelectUserAllAccessQuery, + selectUserAccess: postgresSelectUserAccessQuery, + selectUserReservations: postgresSelectUserReservationsQuery, + selectUserReservationsCount: postgresSelectUserReservationsCountQuery, + selectUserReservationsOwner: postgresSelectUserReservationsOwnerQuery, + selectUserHasReservation: postgresSelectUserHasReservationQuery, + selectOtherAccessCount: postgresSelectOtherAccessCountQuery, + upsertUserAccess: postgresUpsertUserAccessQuery, + deleteUserAccess: postgresDeleteUserAccessQuery, + deleteUserAccessProvisioned: postgresDeleteUserAccessProvisionedQuery, + deleteTopicAccess: postgresDeleteTopicAccessQuery, + deleteAllAccess: postgresDeleteAllAccessQuery, + selectToken: postgresSelectTokenQuery, + selectTokens: postgresSelectTokensQuery, + selectTokenCount: postgresSelectTokenCountQuery, + selectAllProvisionedTokens: postgresSelectAllProvisionedTokensQuery, + upsertToken: postgresUpsertTokenQuery, + updateToken: postgresUpdateTokenQuery, + updateTokenLastAccess: postgresUpdateTokenLastAccessQuery, + deleteToken: postgresDeleteTokenQuery, + deleteProvisionedToken: postgresDeleteProvisionedTokenQuery, + deleteAllToken: postgresDeleteAllTokenQuery, + deleteExpiredTokens: postgresDeleteExpiredTokensQuery, + deleteExcessTokens: postgresDeleteExcessTokensQuery, + insertTier: postgresInsertTierQuery, + selectTiers: postgresSelectTiersQuery, + selectTierByCode: postgresSelectTierByCodeQuery, + selectTierByPriceID: postgresSelectTierByPriceIDQuery, + updateTier: postgresUpdateTierQuery, + deleteTier: postgresDeleteTierQuery, + selectPhoneNumbers: postgresSelectPhoneNumbersQuery, + insertPhoneNumber: postgresInsertPhoneNumberQuery, + deletePhoneNumber: postgresDeletePhoneNumberQuery, + updateBilling: postgresUpdateBillingQuery, +} + +// NewPostgresManager creates a new Manager backed by a PostgreSQL database func NewPostgresManager(db *sql.DB, config *Config) (*Manager, error) { if err := setupPostgres(db); err != nil { return nil, err } - manager := &Manager{ - config: config, - db: db, - statsQueue: make(map[string]*Stats), - tokenQueue: make(map[string]*TokenUpdate), - queries: queries{ - // User queries - selectUserByID: postgresSelectUserByIDQuery, - selectUserByName: postgresSelectUserByNameQuery, - selectUserByToken: postgresSelectUserByTokenQuery, - selectUserByStripeCustomerID: postgresSelectUserByStripeCustomerIDQuery, - selectUsernames: postgresSelectUsernamesQuery, - selectUserCount: postgresSelectUserCountQuery, - selectUserIDFromUsername: postgresSelectUserIDFromUsernameQuery, - insertUser: postgresInsertUserQuery, - updateUserPass: postgresUpdateUserPassQuery, - updateUserRole: postgresUpdateUserRoleQuery, - updateUserProvisioned: postgresUpdateUserProvisionedQuery, - updateUserPrefs: postgresUpdateUserPrefsQuery, - updateUserStats: postgresUpdateUserStatsQuery, - updateUserStatsResetAll: postgresUpdateUserStatsResetAllQuery, - updateUserTier: postgresUpdateUserTierQuery, - updateUserDeleted: postgresUpdateUserDeletedQuery, - deleteUser: postgresDeleteUserQuery, - deleteUserTier: postgresDeleteUserTierQuery, - deleteUsersMarked: postgresDeleteUsersMarkedQuery, - - // Access queries - selectTopicPerms: postgresSelectTopicPermsQuery, - selectUserAllAccess: postgresSelectUserAllAccessQuery, - selectUserAccess: postgresSelectUserAccessQuery, - selectUserReservations: postgresSelectUserReservationsQuery, - selectUserReservationsCount: postgresSelectUserReservationsCountQuery, - selectUserReservationsOwner: postgresSelectUserReservationsOwnerQuery, - selectUserHasReservation: postgresSelectUserHasReservationQuery, - selectOtherAccessCount: postgresSelectOtherAccessCountQuery, - upsertUserAccess: postgresUpsertUserAccessQuery, - deleteUserAccess: postgresDeleteUserAccessQuery, - deleteUserAccessProvisioned: postgresDeleteUserAccessProvisionedQuery, - deleteTopicAccess: postgresDeleteTopicAccessQuery, - deleteAllAccess: postgresDeleteAllAccessQuery, - - // Token queries - selectToken: postgresSelectTokenQuery, - selectTokens: postgresSelectTokensQuery, - selectTokenCount: postgresSelectTokenCountQuery, - selectAllProvisionedTokens: postgresSelectAllProvisionedTokensQuery, - upsertToken: postgresUpsertTokenQuery, - updateToken: postgresUpdateTokenQuery, - updateTokenLastAccess: postgresUpdateTokenLastAccessQuery, - deleteToken: postgresDeleteTokenQuery, - deleteProvisionedToken: postgresDeleteProvisionedTokenQuery, - deleteAllToken: postgresDeleteAllTokenQuery, - deleteExpiredTokens: postgresDeleteExpiredTokensQuery, - deleteExcessTokens: postgresDeleteExcessTokensQuery, - - // Tier queries - insertTier: postgresInsertTierQuery, - selectTiers: postgresSelectTiersQuery, - selectTierByCode: postgresSelectTierByCodeQuery, - selectTierByPriceID: postgresSelectTierByPriceIDQuery, - updateTier: postgresUpdateTierQuery, - deleteTier: postgresDeleteTierQuery, - - // Phone queries - selectPhoneNumbers: postgresSelectPhoneNumbersQuery, - insertPhoneNumber: postgresInsertPhoneNumberQuery, - deletePhoneNumber: postgresDeletePhoneNumberQuery, - - // Billing queries - updateBilling: postgresUpdateBillingQuery, - }, - } - if err := initManager(manager); err != nil { - return nil, err - } - return manager, nil + return newManager(db, postgresQueries, config) } diff --git a/user/manager_sqlite.go b/user/manager_sqlite.go index 2d33087f..e09c682c 100644 --- a/user/manager_sqlite.go +++ b/user/manager_sqlite.go @@ -201,6 +201,63 @@ const ( ` ) +var sqliteQueries = queries{ + selectUserByID: sqliteSelectUserByIDQuery, + selectUserByName: sqliteSelectUserByNameQuery, + selectUserByToken: sqliteSelectUserByTokenQuery, + selectUserByStripeCustomerID: sqliteSelectUserByStripeCustomerIDQuery, + selectUsernames: sqliteSelectUsernamesQuery, + selectUserCount: sqliteSelectUserCountQuery, + selectUserIDFromUsername: sqliteSelectUserIDFromUsernameQuery, + insertUser: sqliteInsertUserQuery, + updateUserPass: sqliteUpdateUserPassQuery, + updateUserRole: sqliteUpdateUserRoleQuery, + updateUserProvisioned: sqliteUpdateUserProvisionedQuery, + updateUserPrefs: sqliteUpdateUserPrefsQuery, + updateUserStats: sqliteUpdateUserStatsQuery, + updateUserStatsResetAll: sqliteUpdateUserStatsResetAllQuery, + updateUserTier: sqliteUpdateUserTierQuery, + updateUserDeleted: sqliteUpdateUserDeletedQuery, + deleteUser: sqliteDeleteUserQuery, + deleteUserTier: sqliteDeleteUserTierQuery, + deleteUsersMarked: sqliteDeleteUsersMarkedQuery, + selectTopicPerms: sqliteSelectTopicPermsQuery, + selectUserAllAccess: sqliteSelectUserAllAccessQuery, + selectUserAccess: sqliteSelectUserAccessQuery, + selectUserReservations: sqliteSelectUserReservationsQuery, + selectUserReservationsCount: sqliteSelectUserReservationsCountQuery, + selectUserReservationsOwner: sqliteSelectUserReservationsOwnerQuery, + selectUserHasReservation: sqliteSelectUserHasReservationQuery, + selectOtherAccessCount: sqliteSelectOtherAccessCountQuery, + upsertUserAccess: sqliteUpsertUserAccessQuery, + deleteUserAccess: sqliteDeleteUserAccessQuery, + deleteUserAccessProvisioned: sqliteDeleteUserAccessProvisionedQuery, + deleteTopicAccess: sqliteDeleteTopicAccessQuery, + deleteAllAccess: sqliteDeleteAllAccessQuery, + selectToken: sqliteSelectTokenQuery, + selectTokens: sqliteSelectTokensQuery, + selectTokenCount: sqliteSelectTokenCountQuery, + selectAllProvisionedTokens: sqliteSelectAllProvisionedTokensQuery, + upsertToken: sqliteUpsertTokenQuery, + updateToken: sqliteUpdateTokenQuery, + updateTokenLastAccess: sqliteUpdateTokenLastAccessQuery, + deleteToken: sqliteDeleteTokenQuery, + deleteProvisionedToken: sqliteDeleteProvisionedTokenQuery, + deleteAllToken: sqliteDeleteAllTokenQuery, + deleteExpiredTokens: sqliteDeleteExpiredTokensQuery, + deleteExcessTokens: sqliteDeleteExcessTokensQuery, + insertTier: sqliteInsertTierQuery, + selectTiers: sqliteSelectTiersQuery, + selectTierByCode: sqliteSelectTierByCodeQuery, + selectTierByPriceID: sqliteSelectTierByPriceIDQuery, + updateTier: sqliteUpdateTierQuery, + deleteTier: sqliteDeleteTierQuery, + selectPhoneNumbers: sqliteSelectPhoneNumbersQuery, + insertPhoneNumber: sqliteInsertPhoneNumberQuery, + deletePhoneNumber: sqliteDeletePhoneNumberQuery, + updateBilling: sqliteUpdateBillingQuery, +} + // NewSQLiteManager creates a new Manager backed by a SQLite database func NewSQLiteManager(filename, startupQueries string, config *Config) (*Manager, error) { parentDir := filepath.Dir(filename) @@ -217,70 +274,5 @@ func NewSQLiteManager(filename, startupQueries string, config *Config) (*Manager if err := runSQLiteStartupQueries(db, startupQueries); err != nil { return nil, err } - manager := &Manager{ - config: config, - db: db, - statsQueue: make(map[string]*Stats), - tokenQueue: make(map[string]*TokenUpdate), - queries: queries{ - selectUserByID: sqliteSelectUserByIDQuery, - selectUserByName: sqliteSelectUserByNameQuery, - selectUserByToken: sqliteSelectUserByTokenQuery, - selectUserByStripeCustomerID: sqliteSelectUserByStripeCustomerIDQuery, - selectUsernames: sqliteSelectUsernamesQuery, - selectUserCount: sqliteSelectUserCountQuery, - selectUserIDFromUsername: sqliteSelectUserIDFromUsernameQuery, - insertUser: sqliteInsertUserQuery, - updateUserPass: sqliteUpdateUserPassQuery, - updateUserRole: sqliteUpdateUserRoleQuery, - updateUserProvisioned: sqliteUpdateUserProvisionedQuery, - updateUserPrefs: sqliteUpdateUserPrefsQuery, - updateUserStats: sqliteUpdateUserStatsQuery, - updateUserStatsResetAll: sqliteUpdateUserStatsResetAllQuery, - updateUserTier: sqliteUpdateUserTierQuery, - updateUserDeleted: sqliteUpdateUserDeletedQuery, - deleteUser: sqliteDeleteUserQuery, - deleteUserTier: sqliteDeleteUserTierQuery, - deleteUsersMarked: sqliteDeleteUsersMarkedQuery, - selectTopicPerms: sqliteSelectTopicPermsQuery, - selectUserAllAccess: sqliteSelectUserAllAccessQuery, - selectUserAccess: sqliteSelectUserAccessQuery, - selectUserReservations: sqliteSelectUserReservationsQuery, - selectUserReservationsCount: sqliteSelectUserReservationsCountQuery, - selectUserReservationsOwner: sqliteSelectUserReservationsOwnerQuery, - selectUserHasReservation: sqliteSelectUserHasReservationQuery, - selectOtherAccessCount: sqliteSelectOtherAccessCountQuery, - upsertUserAccess: sqliteUpsertUserAccessQuery, - deleteUserAccess: sqliteDeleteUserAccessQuery, - deleteUserAccessProvisioned: sqliteDeleteUserAccessProvisionedQuery, - deleteTopicAccess: sqliteDeleteTopicAccessQuery, - deleteAllAccess: sqliteDeleteAllAccessQuery, - selectToken: sqliteSelectTokenQuery, - selectTokens: sqliteSelectTokensQuery, - selectTokenCount: sqliteSelectTokenCountQuery, - selectAllProvisionedTokens: sqliteSelectAllProvisionedTokensQuery, - upsertToken: sqliteUpsertTokenQuery, - updateToken: sqliteUpdateTokenQuery, - updateTokenLastAccess: sqliteUpdateTokenLastAccessQuery, - deleteToken: sqliteDeleteTokenQuery, - deleteProvisionedToken: sqliteDeleteProvisionedTokenQuery, - deleteAllToken: sqliteDeleteAllTokenQuery, - deleteExpiredTokens: sqliteDeleteExpiredTokensQuery, - deleteExcessTokens: sqliteDeleteExcessTokensQuery, - insertTier: sqliteInsertTierQuery, - selectTiers: sqliteSelectTiersQuery, - selectTierByCode: sqliteSelectTierByCodeQuery, - selectTierByPriceID: sqliteSelectTierByPriceIDQuery, - updateTier: sqliteUpdateTierQuery, - deleteTier: sqliteDeleteTierQuery, - selectPhoneNumbers: sqliteSelectPhoneNumbersQuery, - insertPhoneNumber: sqliteInsertPhoneNumberQuery, - deletePhoneNumber: sqliteDeletePhoneNumberQuery, - updateBilling: sqliteUpdateBillingQuery, - }, - } - if err := initManager(manager); err != nil { - return nil, err - } - return manager, nil + return newManager(db, sqliteQueries, config) } diff --git a/user/manager_test.go b/user/manager_test.go index f566e082..fd1e59fc 100644 --- a/user/manager_test.go +++ b/user/manager_test.go @@ -1958,26 +1958,6 @@ func TestStoreTokenRemoveExpired(t *testing.T) { }) } -func TestStoreTokenCreatePrunesExcess(t *testing.T) { - forEachStoreBackend(t, func(t *testing.T, manager *Manager) { - require.Nil(t, manager.AddUser("phil", "mypass", RoleUser, false)) - u, err := manager.User("phil") - require.Nil(t, err) - - // Create several tokens - var tokenValues []string - for i := 0; i < 3; i++ { - tk, err := manager.CreateToken(u.ID, "label", time.Now().Add(time.Duration(i+1)*time.Hour), netip.MustParseAddr("1.2.3.4"), false) - require.Nil(t, err) - tokenValues = append(tokenValues, tk.Value) - } - - tokens, err := manager.Tokens(u.ID) - require.Nil(t, err) - require.True(t, len(tokens) >= 3) - }) -} - func TestStoreTokenUpdateLastAccess(t *testing.T) { forEachStoreBackend(t, func(t *testing.T, manager *Manager) { require.Nil(t, manager.AddUser("phil", "mypass", RoleUser, false))