From 6458f622d23c614235e00f798b1f1f148950afa0 Mon Sep 17 00:00:00 2001 From: Umputun Date: Tue, 11 Sep 2018 11:58:50 -0500 Subject: [PATCH] refactor to combine admin and key store --- backend/app/cmd/server.go | 41 ++----------- backend/app/cmd/server_test.go | 3 +- backend/app/migrator/disqus_test.go | 4 +- backend/app/migrator/migrator_test.go | 10 ++-- backend/app/migrator/remark_test.go | 9 +-- backend/app/migrator/wordpress_test.go | 4 +- backend/app/rest/api/migrator.go | 8 ++- backend/app/rest/api/migrator_test.go | 14 ++--- backend/app/rest/api/rest_test.go | 8 +-- backend/app/rest/auth/auth.go | 6 +- backend/app/rest/auth/auth_test.go | 12 ++-- backend/app/rest/auth/dev_provider_test.go | 4 +- backend/app/rest/auth/jwt.go | 14 +++-- backend/app/rest/auth/jwt_test.go | 16 ++--- backend/app/rest/auth/provider_test.go | 8 +-- backend/app/store/admin/admin.go | 69 +++++++--------------- backend/app/store/admin/admin_test.go | 28 ++++++--- backend/app/store/admin/mongo.go | 61 +++++++++++++++++++ backend/app/store/keys/keys.go | 57 ------------------ backend/app/store/keys/keys_test.go | 58 ------------------ backend/app/store/service/service.go | 6 +- backend/app/store/service/service_test.go | 26 ++++---- 22 files changed, 181 insertions(+), 285 deletions(-) create mode 100644 backend/app/store/admin/mongo.go delete mode 100644 backend/app/store/keys/keys.go delete mode 100644 backend/app/store/keys/keys_test.go diff --git a/backend/app/cmd/server.go b/backend/app/cmd/server.go index d2cce995..bc1a34ac 100644 --- a/backend/app/cmd/server.go +++ b/backend/app/cmd/server.go @@ -24,7 +24,6 @@ import ( "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/avatar" "github.com/umputun/remark/backend/app/store/engine" - "github.com/umputun/remark/backend/app/store/keys" "github.com/umputun/remark/backend/app/store/service" ) @@ -34,7 +33,6 @@ type ServerCommand struct { Avatar AvatarGroup `group:"avatar" namespace:"avatar" env-namespace:"AVATAR"` Cache CacheGroup `group:"cache" namespace:"cache" env-namespace:"CACHE"` Mongo MongoGroup `group:"mongo" namespace:"mongo" env-namespace:"MONGO"` - Key KeyGroup `group:"key" namespace:"key" env-namespace:"KEY"` Admin AdminGroup `group:"admin" namespace:"admin" env-namespace:"ADMIN"` Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","` @@ -105,11 +103,6 @@ type MongoGroup struct { DB string `long:"db" env:"DB" default:"remark42" description:"mongo database"` } -// KeyGroup defines options group for key params -type KeyGroup struct { - Type string `long:"type" env:"TYPE" description:"type of key store" choice:"shared" choice:"mongo" default:"shared"` -} - // AdminGroup defines options group for admin params type AdminGroup struct { Type string `long:"type" env:"TYPE" description:"type of admin store" choice:"shared" choice:"mongo" default:"shared"` @@ -174,12 +167,6 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) { return nil, errors.Wrap(err, "failed to make data store engine") } - keyStore, err := s.makeKeyStore() - if err != nil { - return nil, errors.Wrap(err, "failed to make key store") - - } - adminStore, err := s.makeAdminStore() if err != nil { return nil, errors.Wrap(err, "failed to make admin store") @@ -188,7 +175,6 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) { dataService := &service.DataStore{ Interface: storeEngine, EditDuration: s.EditDuration, - KeyStore: keyStore, AdminStore: adminStore, MaxCommentSize: s.MaxCommentSize, } @@ -199,7 +185,7 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) { } // token TTL is 5 minutes, inactivity interval 7+ days by default - jwtService := auth.NewJWT(keyStore, strings.HasPrefix(s.RemarkURL, "https://"), s.Auth.TTL.JWT, s.Auth.TTL.Cookie) + jwtService := auth.NewJWT(adminStore, strings.HasPrefix(s.RemarkURL, "https://"), s.Auth.TTL.JWT, s.Auth.TTL.Cookie) avatarStore, err := s.makeAvatarStore() if err != nil { @@ -219,7 +205,7 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) { DisqusImporter: &migrator.Disqus{DataStore: dataService}, WordPressImporter: &migrator.WordPress{DataStore: dataService}, NativeExported: &migrator.Remark{DataStore: dataService}, - KeyStore: keyStore, + KeyStore: adminStore, } authProviders := s.makeAuthProviders(jwtService, avatarProxy, dataService) @@ -243,7 +229,6 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) { Providers: authProviders, DevPasswd: s.DevPasswd, PermissionChecker: dataService, - KeyStore: keyStore, }, Cache: loadingCache, } @@ -359,24 +344,6 @@ func (s *ServerCommand) makeAvatarStore() (avatar.Store, error) { return nil, errors.Errorf("unsupported avatar store type %s", s.Avatar.Type) } -func (s *ServerCommand) makeKeyStore() (keys.Store, error) { - log.Printf("[INFO] make key store, type=%s", s.Admin.Type) - - switch s.Key.Type { - case "shared": - return keys.NewStaticStore(s.SharedSecret), nil - case "mongo": - mgServer, e := s.makeMongo() - if e != nil { - return nil, errors.Wrap(e, "failed to create mongo server") - } - conn := mongo.NewConnection(mgServer, s.Mongo.DB, "admin") - return keys.NewMongoStore(conn), nil - default: - return nil, errors.Errorf("unsupported key store type %s", s.Key.Type) - } -} - func (s *ServerCommand) makeAdminStore() (admin.Store, error) { log.Printf("[INFO] make admin store, type=%s", s.Admin.Type) @@ -387,7 +354,7 @@ func (s *ServerCommand) makeAdminStore() (admin.Store, error) { s.Admin.Shared.Email = "admin@" + u.Host } } - return admin.NewStaticStore(s.Admin.Shared.Admins, s.Admin.Shared.Email), nil + return admin.NewStaticStore(s.SharedSecret, s.Admin.Shared.Admins, s.Admin.Shared.Email), nil case "mongo": mgServer, e := s.makeMongo() if e != nil { @@ -396,7 +363,7 @@ func (s *ServerCommand) makeAdminStore() (admin.Store, error) { conn := mongo.NewConnection(mgServer, s.Mongo.DB, "admin") return admin.NewMongoStore(conn), nil default: - return nil, errors.Errorf("unsupported admin store type %s", s.Key.Type) + return nil, errors.Errorf("unsupported admin store type %s", s.Admin.Type) } } diff --git a/backend/app/cmd/server_test.go b/backend/app/cmd/server_test.go index c2985795..67eddf62 100644 --- a/backend/app/cmd/server_test.go +++ b/backend/app/cmd/server_test.go @@ -91,8 +91,7 @@ func TestServerApp_WithMongo(t *testing.T) { // prepare options p := flags.NewParser(&opts, flags.Default) _, err := p.ParseArgs([]string{"--dev-passwd=password", "--cache.type=mongo", "--store.type=mongo", - "--avatar.type=mongo", "--mongo.url=" + mongoURL, "--mongo.db=test_remark", "--port=12345", - "--key.type=mongo", "--admin.type=mongo"}) + "--avatar.type=mongo", "--mongo.url=" + mongoURL, "--mongo.db=test_remark", "--port=12345", "--admin.type=mongo"}) require.Nil(t, err) opts.Auth.Github.CSEC, opts.Auth.Github.CID = "csec", "cid" opts.BackupLocation = "/tmp" diff --git a/backend/app/migrator/disqus_test.go b/backend/app/migrator/disqus_test.go index a8e435e3..cbb021a4 100644 --- a/backend/app/migrator/disqus_test.go +++ b/backend/app/migrator/disqus_test.go @@ -9,8 +9,8 @@ import ( "github.com/coreos/bbolt" "github.com/stretchr/testify/require" "github.com/umputun/remark/backend/app/store" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/engine" - "github.com/umputun/remark/backend/app/store/keys" "github.com/umputun/remark/backend/app/store/service" "github.com/stretchr/testify/assert" @@ -20,7 +20,7 @@ func TestDisqus_Import(t *testing.T) { defer os.Remove("/tmp/remark-test.db") b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"}) require.Nil(t, err, "create store") - dataStore := service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")} + dataStore := service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")} d := Disqus{DataStore: &dataStore} size, err := d.Import(strings.NewReader(xmlTestDisqus), "test") assert.Nil(t, err) diff --git a/backend/app/migrator/migrator_test.go b/backend/app/migrator/migrator_test.go index 2ec70199..0ebcd09e 100644 --- a/backend/app/migrator/migrator_test.go +++ b/backend/app/migrator/migrator_test.go @@ -8,10 +8,10 @@ import ( "github.com/coreos/bbolt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/umputun/remark/backend/app/store/keys" - "github.com/umputun/remark/backend/app/store/service" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/engine" + "github.com/umputun/remark/backend/app/store/service" ) func TestMigrator_ImportDisqus(t *testing.T) { @@ -25,7 +25,7 @@ func TestMigrator_ImportDisqus(t *testing.T) { b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"}) require.Nil(t, err, "create store") - dataStore := &service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")} + dataStore := &service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")} size, err := ImportComments(ImportParams{ DataStore: dataStore, InputFile: "/tmp/disqus-test.xml", @@ -51,7 +51,7 @@ func TestMigrator_ImportWordPress(t *testing.T) { b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"}) require.Nil(t, err, "create store") - dataStore := &service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")} + dataStore := &service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")} size, err := ImportComments(ImportParams{ DataStore: dataStore, InputFile: "/tmp/wordpress-test.xml", @@ -80,7 +80,7 @@ func TestMigrator_ImportRemark(t *testing.T) { b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "radio-t"}) require.Nil(t, err, "create store") - dataStore := &service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")} + dataStore := &service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")} size, err := ImportComments(ImportParams{ DataStore: dataStore, diff --git a/backend/app/migrator/remark_test.go b/backend/app/migrator/remark_test.go index 7c0621de..78a50766 100644 --- a/backend/app/migrator/remark_test.go +++ b/backend/app/migrator/remark_test.go @@ -10,9 +10,10 @@ import ( "github.com/coreos/bbolt" "github.com/stretchr/testify/assert" + "github.com/umputun/remark/backend/app/store" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/engine" - "github.com/umputun/remark/backend/app/store/keys" "github.com/umputun/remark/backend/app/store/service" ) @@ -50,7 +51,7 @@ func TestRemark_Import(t *testing.T) { os.Remove(testDb) b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{SiteID: "radio-t", FileName: testDb}) assert.Nil(t, err) - r := Remark{DataStore: &service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")}} + r := Remark{DataStore: &service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}} size, err := r.Import(buf, "radio-t") assert.Nil(t, err) assert.Equal(t, 2, size) @@ -78,7 +79,7 @@ func TestRemark_ImportManyWithError(t *testing.T) { os.Remove(testDb) b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{SiteID: "radio-t", FileName: testDb}) assert.Nil(t, err) - r := Remark{DataStore: &service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")}} + r := Remark{DataStore: &service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}} n, err := r.Import(buf, "radio-t") assert.EqualError(t, err, "failed to save 2 comments") assert.Equal(t, 1200, n) @@ -94,7 +95,7 @@ func prep(t *testing.T) *service.DataStore { boltStore, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{SiteID: "radio-t", FileName: testDb}) assert.Nil(t, err) - b := &service.DataStore{Interface: boltStore, KeyStore: keys.NewStaticStore("12345")} + b := &service.DataStore{Interface: boltStore, AdminStore: admin.NewStaticStore("12345", []string{}, "")} comment := store.Comment{ ID: "efbc17f177ee1a1c0ee6e1e025749966ec071adc", diff --git a/backend/app/migrator/wordpress_test.go b/backend/app/migrator/wordpress_test.go index ae71e4d3..09769b56 100644 --- a/backend/app/migrator/wordpress_test.go +++ b/backend/app/migrator/wordpress_test.go @@ -8,9 +8,9 @@ import ( "github.com/coreos/bbolt" "github.com/stretchr/testify/assert" - "github.com/umputun/remark/backend/app/store/keys" "github.com/umputun/remark/backend/app/store" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/engine" "github.com/umputun/remark/backend/app/store/service" ) @@ -21,7 +21,7 @@ func TestWordPress_Import(t *testing.T) { b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: siteID}) assert.Nil(t, err, "create store") - dataStore := service.DataStore{Interface: b, KeyStore: keys.NewStaticStore("12345")} + dataStore := service.DataStore{Interface: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")} wp := WordPress{DataStore: &dataStore} size, err := wp.Import(strings.NewReader(xmlTestWP), siteID) assert.Nil(t, err) diff --git a/backend/app/rest/api/migrator.go b/backend/app/rest/api/migrator.go index 01534e4d..b781cc20 100644 --- a/backend/app/rest/api/migrator.go +++ b/backend/app/rest/api/migrator.go @@ -14,7 +14,6 @@ import ( "github.com/umputun/remark/backend/app/migrator" "github.com/umputun/remark/backend/app/rest" "github.com/umputun/remark/backend/app/rest/cache" - "github.com/umputun/remark/backend/app/store/keys" ) // Migrator rest with import and export controllers @@ -24,7 +23,12 @@ type Migrator struct { DisqusImporter migrator.Importer WordPressImporter migrator.Importer NativeExported migrator.Exporter - KeyStore keys.Store + KeyStore KeyStore +} + +// KeyStore defines sub-interface for consumers needed just a key +type KeyStore interface { + Key(siteID string) (key string, err error) } func (m *Migrator) withRoutes(router chi.Router) chi.Router { diff --git a/backend/app/rest/api/migrator_test.go b/backend/app/rest/api/migrator_test.go index eb0c2b52..6771d37a 100644 --- a/backend/app/rest/api/migrator_test.go +++ b/backend/app/rest/api/migrator_test.go @@ -22,7 +22,6 @@ import ( "github.com/umputun/remark/backend/app/store" adminstore "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/engine" - "github.com/umputun/remark/backend/app/store/keys" "github.com/umputun/remark/backend/app/store/service" ) @@ -153,29 +152,28 @@ func TestMigrator_Export(t *testing.T) { func prepImportSrv(t *testing.T) (svc *Migrator, ds *service.DataStore, ts *httptest.Server) { b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: testDb, SiteID: "radio-t"}) require.Nil(t, err) - ks := keys.NewStaticStore("123456") - dataStore := &service.DataStore{Interface: b, KeyStore: ks} + adminStore := adminstore.NewStaticStore("123456", []string{"a1", "a2"}, "admin@remark-42.com") + dataStore := &service.DataStore{Interface: b, AdminStore: adminStore} svc = &Migrator{ DisqusImporter: &migrator.Disqus{DataStore: dataStore}, WordPressImporter: &migrator.WordPress{DataStore: dataStore}, NativeImporter: &migrator.Remark{DataStore: dataStore}, NativeExported: &migrator.Remark{DataStore: dataStore}, Cache: &cache.Nop{}, - KeyStore: ks, + KeyStore: adminStore, } a := auth.Authenticator{ DevPasswd: "password", Providers: nil, - AdminStore: adminstore.NewStaticStore([]string{"a1", "a2"}, "admin@remark-42.com"), - JWTService: auth.NewJWT(keys.NewStaticStore("123456"), false, time.Minute, time.Hour), - KeyStore: ks, + AdminStore: adminStore, + JWTService: auth.NewJWT(adminStore, false, time.Minute, time.Hour), } routes := svc.withRoutes(chi.NewRouter().With(a.Auth(true)).With(a.AdminOnly)) ts = httptest.NewServer(routes) return svc, dataStore, ts } -func cleanupImportSrv(m *Migrator, ts *httptest.Server) { +func cleanupImportSrv(_ *Migrator, ts *httptest.Server) { ts.Close() os.Remove(testDb) } diff --git a/backend/app/rest/api/rest_test.go b/backend/app/rest/api/rest_test.go index df27dacf..666caed5 100644 --- a/backend/app/rest/api/rest_test.go +++ b/backend/app/rest/api/rest_test.go @@ -23,7 +23,6 @@ import ( adminstore "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/avatar" "github.com/umputun/remark/backend/app/store/engine" - "github.com/umputun/remark/backend/app/store/keys" "github.com/umputun/remark/backend/app/store/service" ) @@ -92,13 +91,12 @@ func prep(t *testing.T) (srv *Rest, ts *httptest.Server) { b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: testDb, SiteID: "radio-t"}) require.Nil(t, err) - adminStore := adminstore.NewStaticStore([]string{"a1", "a2"}, "admin@remark-42.com") + adminStore := adminstore.NewStaticStore("123456", []string{"a1", "a2"}, "admin@remark-42.com") dataStore := &service.DataStore{ Interface: b, EditDuration: 5 * time.Minute, MaxCommentSize: 4000, - KeyStore: keys.NewStaticStore("123456"), AdminStore: adminStore, } srv = &Rest{ @@ -107,7 +105,7 @@ func prep(t *testing.T) (srv *Rest, ts *httptest.Server) { DevPasswd: "password", Providers: nil, AdminStore: adminStore, - JWTService: auth.NewJWT(keys.NewStaticStore("123456"), false, time.Minute, time.Hour), + JWTService: auth.NewJWT(adminStore, false, time.Minute, time.Hour), }, Cache: &cache.Nop{}, WebRoot: "/tmp", @@ -122,7 +120,7 @@ func prep(t *testing.T) (srv *Rest, ts *httptest.Server) { NativeImporter: &migrator.Remark{DataStore: dataStore}, NativeExported: &migrator.Remark{DataStore: dataStore}, Cache: &cache.Nop{}, - KeyStore: keys.NewStaticStore("123456"), + KeyStore: adminStore, }, } srv.ScoreThresholds.Low, srv.ScoreThresholds.Critical = -5, -10 diff --git a/backend/app/rest/auth/auth.go b/backend/app/rest/auth/auth.go index cd3d7248..758924ab 100644 --- a/backend/app/rest/auth/auth.go +++ b/backend/app/rest/auth/auth.go @@ -10,7 +10,6 @@ import ( "github.com/umputun/remark/backend/app/rest" "github.com/umputun/remark/backend/app/store" "github.com/umputun/remark/backend/app/store/admin" - "github.com/umputun/remark/backend/app/store/keys" ) // Authenticator is top level auth object providing middlewares @@ -18,7 +17,6 @@ type Authenticator struct { JWTService *JWT Providers []Provider AdminStore admin.Store - KeyStore keys.Store DevPasswd string PermissionChecker PermissionChecker } @@ -114,14 +112,14 @@ func (a *Authenticator) Auth(reqAuth bool) func(http.Handler) http.Handler { } func (a *Authenticator) checkSecretKey(r *http.Request) bool { - if a.KeyStore == nil { + if a.AdminStore == nil { return false } siteID := r.URL.Query().Get("site") secret := r.URL.Query().Get("secret") - skey, err := a.KeyStore.Get(siteID) + skey, err := a.AdminStore.Key(siteID) if err != nil { return false } diff --git a/backend/app/rest/auth/auth_test.go b/backend/app/rest/auth/auth_test.go index 4efc80f9..2216f1bd 100644 --- a/backend/app/rest/auth/auth_test.go +++ b/backend/app/rest/auth/auth_test.go @@ -11,7 +11,7 @@ import ( "github.com/go-chi/chi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/umputun/remark/backend/app/store/keys" + "github.com/umputun/remark/backend/app/store/admin" ) var testJwtUserBlocked = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFkbWluIjpmYWxzZSwiYmxvY2siOnRydWV9LCJzdGF0ZSI6IjEyMzQ1NiIsImZyb20iOiJmcm9tIn0.6P_OwGf8CUJRtvNSlW20GmaMb5pFvCNemP94fHCqb5Q" @@ -19,7 +19,7 @@ var testJwtUserBlocked = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxO var testJwtDeleteMe = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFkbWluIjpmYWxzZSwiYmxvY2siOmZhbHNlfSwiZmxhZ3MiOnsiZGVsZXRlbWUiOnRydWV9fQ.SLh1QpFytWZqcT99VgcdAOtgFKhvpKCcZwqWTvAd63g" func TestAuthJWTCookie(t *testing.T) { - a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, time.Hour), + a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, time.Hour), PermissionChecker: &mockUserPermissions{}} router := chi.NewRouter() router.With(a.Auth(true)).Get("/auth", func(w http.ResponseWriter, r *http.Request) { @@ -57,7 +57,7 @@ func TestAuthJWTCookie(t *testing.T) { } func TestAuthJWTHeader(t *testing.T) { - a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, time.Hour)} + a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, time.Hour)} router := chi.NewRouter() router.With(a.Auth(true)).Get("/auth", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(201) @@ -84,7 +84,7 @@ func TestAuthJWTHeader(t *testing.T) { } func TestAuthJWtBlocked(t *testing.T) { - a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, time.Hour)} + a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, time.Hour)} router := chi.NewRouter() router.With(a.Auth(true)).Get("/auth", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(201) @@ -104,7 +104,7 @@ func TestAuthJWtBlocked(t *testing.T) { } func TestAuthJWtFlags(t *testing.T) { - a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, time.Hour)} + a := Authenticator{DevPasswd: "123456", JWTService: NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, time.Hour)} router := chi.NewRouter() router.With(a.Auth(true)).Get("/auth", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(201) @@ -213,7 +213,7 @@ func TestAdminRequired(t *testing.T) { } func TestAuthWithSecret(t *testing.T) { - a := Authenticator{DevPasswd: "123456", KeyStore: keys.NewStaticStore("secretkey")} + a := Authenticator{DevPasswd: "123456", AdminStore: admin.NewStaticKeyStore("secretkey")} router := chi.NewRouter() router.With(a.Auth(true), a.AdminOnly).Get("/auth", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(201) diff --git a/backend/app/rest/auth/dev_provider_test.go b/backend/app/rest/auth/dev_provider_test.go index 8f768baa..6a732bfe 100644 --- a/backend/app/rest/auth/dev_provider_test.go +++ b/backend/app/rest/auth/dev_provider_test.go @@ -13,12 +13,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/umputun/remark/backend/app/store" - "github.com/umputun/remark/backend/app/store/keys" + "github.com/umputun/remark/backend/app/store/admin" ) func TestDevProvider(t *testing.T) { params := Params{RemarkURL: "http://127.0.0.1:8080", Cid: "cid", Csecret: "csecret", - JwtService: NewJWT(keys.NewStaticStore("12345"), false, time.Hour, time.Hour*24*31), + JwtService: NewJWT(admin.NewStaticKeyStore("12345"), false, time.Hour, time.Hour*24*31), PermissionChecker: &mockUserPermissions{admin: "dev_user"}, } srv := DevAuthServer{Provider: NewDev(params), nonInteractive: true, username: "dev_user"} diff --git a/backend/app/rest/auth/jwt.go b/backend/app/rest/auth/jwt.go index d6fd3c06..a95f2934 100644 --- a/backend/app/rest/auth/jwt.go +++ b/backend/app/rest/auth/jwt.go @@ -8,13 +8,12 @@ import ( "github.com/pkg/errors" "github.com/umputun/remark/backend/app/store" - "github.com/umputun/remark/backend/app/store/keys" ) // JWT wraps jwt operations // supports both header and cookie jwt type JWT struct { - keyStore keys.Store + keyStore KeyStore secureCookies bool tokenDuration time.Duration cookieDuration time.Duration @@ -43,8 +42,13 @@ const jwtHeaderKey = "X-JWT" const xsrfCookieName = "XSRF-TOKEN" const xsrfHeaderKey = "X-XSRF-TOKEN" +// KeyStore defines sub-interface for consumers needed just a key +type KeyStore interface { + Key(siteID string) (key string, err error) +} + // NewJWT makes JWT service -func NewJWT(keyStore keys.Store, secureCookies bool, tokenDuration time.Duration, cookieDuration time.Duration) *JWT { +func NewJWT(keyStore KeyStore, secureCookies bool, tokenDuration time.Duration, cookieDuration time.Duration) *JWT { res := JWT{ keyStore: keyStore, secureCookies: secureCookies, @@ -58,7 +62,7 @@ func NewJWT(keyStore keys.Store, secureCookies bool, tokenDuration time.Duration func (j *JWT) Token(claims *CustomClaims) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - secret, err := j.keyStore.Get(claims.SiteID) + secret, err := j.keyStore.Key(claims.SiteID) if err != nil { return "", errors.Wrap(err, "can't get secret") } @@ -96,7 +100,7 @@ func (j *JWT) Parse(tokenString string) (*CustomClaims, error) { return nil, errors.Wrap(err, "failed to get siteID from jwt token") } - secret, err := j.keyStore.Get(siteID) + secret, err := j.keyStore.Key(siteID) if err != nil { return nil, errors.Wrap(err, "can't get secret") } diff --git a/backend/app/rest/auth/jwt_test.go b/backend/app/rest/auth/jwt_test.go index f1ce7efa..f1e654d8 100644 --- a/backend/app/rest/auth/jwt_test.go +++ b/backend/app/rest/auth/jwt_test.go @@ -10,7 +10,7 @@ import ( "github.com/dgrijalva/jwt-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/umputun/remark/backend/app/store/keys" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store" ) @@ -30,7 +30,7 @@ var testJwtBadSign = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4M var days31 = time.Hour * 24 * 31 func TestJWT_Token(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) claims := &CustomClaims{ State: "123456", @@ -53,7 +53,7 @@ func TestJWT_Token(t *testing.T) { } func TestJWT_Parse(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) claims, err := j.Parse(testJwtValid) assert.NoError(t, err) assert.False(t, j.IsExpired(claims)) @@ -71,7 +71,7 @@ func TestJWT_Parse(t *testing.T) { } func TestJWT_Set(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) claims := &CustomClaims{ State: "123456", @@ -116,7 +116,7 @@ func TestJWT_Set(t *testing.T) { } func TestJWT_GetFromHeader(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) req := httptest.NewRequest("GET", "/", nil) req.Header.Add(jwtHeaderKey, testJwtValid) @@ -141,7 +141,7 @@ func TestJWT_GetFromHeader(t *testing.T) { } func TestJWT_SetAndGetWithCookies(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) claims := &CustomClaims{ State: "123456", @@ -183,7 +183,7 @@ func TestJWT_SetAndGetWithCookies(t *testing.T) { } func TestJWT_SetAndGetWithXsrfMismatch(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) claims := &CustomClaims{ State: "123456", @@ -220,7 +220,7 @@ func TestJWT_SetAndGetWithXsrfMismatch(t *testing.T) { } func TestJWT_SetAndGetWithCookiesExpired(t *testing.T) { - j := NewJWT(keys.NewStaticStore("xyz 12345"), false, time.Hour, days31) + j := NewJWT(admin.NewStaticKeyStore("xyz 12345"), false, time.Hour, days31) claims := &CustomClaims{ State: "123456", diff --git a/backend/app/rest/auth/provider_test.go b/backend/app/rest/auth/provider_test.go index be78d789..c2b41616 100644 --- a/backend/app/rest/auth/provider_test.go +++ b/backend/app/rest/auth/provider_test.go @@ -13,10 +13,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/umputun/remark/backend/app/store/keys" "golang.org/x/oauth2" "github.com/umputun/remark/backend/app/store" + "github.com/umputun/remark/backend/app/store/admin" ) func TestLogin(t *testing.T) { @@ -54,7 +54,7 @@ func TestLogin(t *testing.T) { Admin: false, Blocked: true, IP: ""}, u) token := resp.Cookies()[0].Value - jwtSvc := NewJWT(keys.NewStaticStore("12345"), false, time.Hour, time.Hour*24*31) + jwtSvc := NewJWT(admin.NewStaticKeyStore("12345"), false, time.Hour, time.Hour*24*31) claims, err := jwtSvc.Parse(token) require.NoError(t, err) @@ -103,7 +103,7 @@ func TestLoginSessionOnly(t *testing.T) { req.AddCookie(resp.Cookies()[1]) req.Header.Add("X-XSRF-TOKEN", resp.Cookies()[1].Value) - jwtService := NewJWT(keys.NewStaticStore("12345"), false, time.Hour, time.Hour) + jwtService := NewJWT(admin.NewStaticKeyStore("12345"), false, time.Hour, time.Hour) res, err := jwtService.Get(req) require.Nil(t, err) assert.Equal(t, true, res.SessionOnly) @@ -169,7 +169,7 @@ func mockProvider(t *testing.T, loginPort, authPort int) (*http.Server, *http.Se } params := Params{RemarkURL: "url", Cid: "cid", Csecret: "csecret", - JwtService: NewJWT(keys.NewStaticStore("12345"), false, time.Hour, time.Hour*24*31), + JwtService: NewJWT(admin.NewStaticKeyStore("12345"), false, time.Hour, time.Hour*24*31), // AvatarProxy: &proxy.Avatar{Store: &mockAvatarStore, RoutePath: "/v1/avatar"}, PermissionChecker: &mockUserPermissions{admin: "mock_myuser2", verified: "mock_myuser2", blocked: "mock_myuser1"}, } diff --git a/backend/app/store/admin/admin.go b/backend/app/store/admin/admin.go index 05068e3e..2e2815b4 100644 --- a/backend/app/store/admin/admin.go +++ b/backend/app/store/admin/admin.go @@ -1,15 +1,15 @@ +// Package admin defines and implements store for admin-level data like secret key, list of admins and so on + package admin import ( + "errors" "log" - - "github.com/globalsign/mgo" - "github.com/globalsign/mgo/bson" - "github.com/go-pkgz/mongo" ) // Store defines interface returning admins info for given site type Store interface { + Key(siteID string) (key string, err error) Admins(siteID string) (ids []string) Email(siteID string) (email string) } @@ -18,12 +18,26 @@ type Store interface { type StaticStore struct { admins []string email string + key string +} + +// Key returns static key for all sites, allows empty site +func (s *StaticStore) Key(siteID string) (key string, err error) { + if s.key == "" { + return "", errors.New("empty key for static key store") + } + return s.key, nil } // NewStaticStore makes StaticStore instance with given key -func NewStaticStore(admins []string, email string) *StaticStore { +func NewStaticStore(key string, admins []string, email string) *StaticStore { log.Printf("[DEBUG] admin users %+v, email %s", admins, email) - return &StaticStore{admins: admins, email: email} + return &StaticStore{key: key, admins: admins, email: email} +} + +// NewStaticKeyStore is a shortcut for making StaticStore for key consumers only +func NewStaticKeyStore(key string) *StaticStore { + return &StaticStore{key: key, admins: []string{}, email: ""} } // Admins returns static list of admin's ids, the same for all sites @@ -35,46 +49,3 @@ func (s *StaticStore) Admins(string) (ids []string) { func (s *StaticStore) Email(string) (email string) { return s.email } - -// MongoStore implements admin.Store with mongo backend -type MongoStore struct { - connection *mongo.Connection -} - -// NewMongoStore makes admin Store for mongo's connection -func NewMongoStore(conn *mongo.Connection) *MongoStore { - log.Printf("[DEBUG] make mongo admin store with %+v", conn) - return &MongoStore{connection: conn} -} - -// Admins executes find by siteID and returns admins ids -func (m *MongoStore) Admins(siteID string) (ids []string) { - resp := struct { - SiteID string `bson:"site"` - IDs []string `bson:"admin_ids"` - Email string `bson:"admin_email"` - }{} - err := m.connection.WithCollection(func(coll *mgo.Collection) error { - return coll.Find(bson.M{"site": siteID}).One(&resp) - }) - if err != nil { - return []string{} - } - return resp.IDs -} - -// Email executes find by siteID and returns admin's email -func (m *MongoStore) Email(siteID string) (email string) { - resp := struct { - SiteID string `bson:"site"` - IDs []string `bson:"admin_ids"` - Email string `bson:"admin_email"` - }{} - err := m.connection.WithCollection(func(coll *mgo.Collection) error { - return coll.Find(bson.M{"site": siteID}).One(&resp) - }) - if err != nil { - return "" - } - return resp.Email -} diff --git a/backend/app/store/admin/admin_test.go b/backend/app/store/admin/admin_test.go index 73cf5db3..ebbbec1e 100644 --- a/backend/app/store/admin/admin_test.go +++ b/backend/app/store/admin/admin_test.go @@ -10,13 +10,21 @@ import ( ) func TestStaticStore_Get(t *testing.T) { - var ks Store = NewStaticStore([]string{"123", "xyz"}, "aa@example.com") + var ks Store = NewStaticStore("key123", []string{"123", "xyz"}, "aa@example.com") + + k, err := ks.Key("any") + assert.NoError(t, err, "valid store") + assert.Equal(t, "key123", k, "valid site") a := ks.Admins("any") assert.Equal(t, []string{"123", "xyz"}, a) email := ks.Email("blah") assert.Equal(t, "aa@example.com", email) + + ks = NewStaticStore("", []string{"123", "xyz"}, "aa@example.com") + _, err = ks.Key("any") + assert.NotNil(t, err, "invalid (empty key) store") } func TestMongoStore_Get(t *testing.T) { @@ -24,13 +32,9 @@ func TestMongoStore_Get(t *testing.T) { require.NoError(t, err) var ms Store = NewMongoStore(conn) - recs := []struct { - SiteID string `bson:"site"` - IDs []string `bson:"admin_ids"` - Email string `bson:"admin_email"` - }{ - {"site1", []string{"i11", "i12"}, "e1"}, - {"site2", []string{"i21", "i22"}, "e2"}, + recs := []mongoRec{ + {"site1", "secret1", []string{"i11", "i12"}, "e1"}, + {"site2", "secret2", []string{"i21", "i22"}, "e2"}, } err = conn.WithCollection(func(coll *mgo.Collection) error { if e1 := coll.Insert(recs[0]); e1 != nil { @@ -47,14 +51,22 @@ func TestMongoStore_Get(t *testing.T) { assert.Equal(t, []string{"i11", "i12"}, admins) email := ms.Email("site1") assert.Equal(t, "e1", email) + key, err := ms.Key("site1") + assert.NoError(t, err) + assert.Equal(t, "secret1", key) admins = ms.Admins("site2") assert.Equal(t, []string{"i21", "i22"}, admins) email = ms.Email("site2") assert.Equal(t, "e2", email) + key, err = ms.Key("site2") + assert.NoError(t, err) + assert.Equal(t, "secret2", key) admins = ms.Admins("no-site-in-db") assert.Equal(t, []string{}, admins) email = ms.Email("no-site-in-db") assert.Equal(t, "", email) + _, err = ms.Key("no-site-in-db") + assert.Error(t, err, "can't get secret for site no-site-in-db") } diff --git a/backend/app/store/admin/mongo.go b/backend/app/store/admin/mongo.go new file mode 100644 index 00000000..ddd98ac8 --- /dev/null +++ b/backend/app/store/admin/mongo.go @@ -0,0 +1,61 @@ +package admin + +import ( + "log" + + "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" + "github.com/go-pkgz/mongo" + "github.com/pkg/errors" +) + +// MongoStore implements admin.Store with mongo backend +type MongoStore struct { + connection *mongo.Connection +} + +type mongoRec struct { + SiteID string `bson:"site"` + SecretKey string `bson:"secret"` + IDs []string `bson:"admin_ids"` + Email string `bson:"admin_email"` +} + +// NewMongoStore makes admin Store for mongo's connection +func NewMongoStore(conn *mongo.Connection) *MongoStore { + log.Printf("[DEBUG] make mongo admin store with %+v", conn) + return &MongoStore{connection: conn} +} + +// Key executes find by siteID and returns substructure with secret key +func (m *MongoStore) Key(siteID string) (key string, err error) { + resp := mongoRec{} + err = m.connection.WithCollection(func(coll *mgo.Collection) error { + return coll.Find(bson.M{"site": siteID}).One(&resp) + }) + return resp.SecretKey, errors.Wrapf(err, "can't get secret for site %s", siteID) +} + +// Admins executes find by siteID and returns admins ids +func (m *MongoStore) Admins(siteID string) (ids []string) { + resp := mongoRec{} + err := m.connection.WithCollection(func(coll *mgo.Collection) error { + return coll.Find(bson.M{"site": siteID}).One(&resp) + }) + if err != nil { + return []string{} + } + return resp.IDs +} + +// Email executes find by siteID and returns admin's email +func (m *MongoStore) Email(siteID string) (email string) { + resp := mongoRec{} + err := m.connection.WithCollection(func(coll *mgo.Collection) error { + return coll.Find(bson.M{"site": siteID}).One(&resp) + }) + if err != nil { + return "" + } + return resp.Email +} diff --git a/backend/app/store/keys/keys.go b/backend/app/store/keys/keys.go deleted file mode 100644 index 588bf5c6..00000000 --- a/backend/app/store/keys/keys.go +++ /dev/null @@ -1,57 +0,0 @@ -package keys - -import ( - "log" - - "github.com/globalsign/mgo" - "github.com/globalsign/mgo/bson" - "github.com/go-pkgz/mongo" - "github.com/pkg/errors" -) - -// Store defines interface returning key for given site -// this key used for JWT and HMAC hashes -type Store interface { - Get(siteID string) (key string, err error) -} - -// StaticStore implements keys.Store with a single, predefined key -type StaticStore struct { - key string -} - -// NewStaticStore makes StaticStore instance with given key -func NewStaticStore(key string) *StaticStore { - return &StaticStore{key: key} -} - -// Get returns static key for all sites, allows empty site -func (s *StaticStore) Get(siteID string) (key string, err error) { - if s.key == "" { - return "", errors.New("empty key for static key store") - } - return s.key, nil -} - -// MongoStore implements keys.Store with mongo backend -type MongoStore struct { - connection *mongo.Connection -} - -// NewMongoStore makes keys Store for mongo's connection -func NewMongoStore(conn *mongo.Connection) *MongoStore { - log.Printf("[DEBUG] make mongo keys store with %+v", conn) - return &MongoStore{connection: conn} -} - -// Get executes find by siteID and returns substructure with secret key -func (m *MongoStore) Get(siteID string) (key string, err error) { - resp := struct { - SiteID string `bson:"site"` - SecretKey string `bson:"secret"` - }{} - err = m.connection.WithCollection(func(coll *mgo.Collection) error { - return coll.Find(bson.M{"site": siteID}).One(&resp) - }) - return resp.SecretKey, errors.Wrapf(err, "can't get secret for site %s", siteID) -} diff --git a/backend/app/store/keys/keys_test.go b/backend/app/store/keys/keys_test.go deleted file mode 100644 index 0364c200..00000000 --- a/backend/app/store/keys/keys_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package keys - -import ( - "testing" - - "github.com/globalsign/mgo" - "github.com/go-pkgz/mongo" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestStaticStore_Get(t *testing.T) { - var ks Store = NewStaticStore("key123") - - k, err := ks.Get("any") - assert.NoError(t, err, "valid store") - assert.Equal(t, "key123", k, "valid site") - - ks = NewStaticStore("") - - _, err = ks.Get("any") - assert.NotNil(t, err, "invalid (empty key) store") -} - -func TestMongoStore_Get(t *testing.T) { - conn, err := mongo.MakeTestConnection(t) - require.NoError(t, err) - var ms Store = NewMongoStore(conn) - - recs := []struct { - SiteID string `bson:"site"` - SecretKey string `bson:"secret"` - }{ - {"site1", "secret1"}, - {"site2", "secret2"}, - } - err = conn.WithCollection(func(coll *mgo.Collection) error { - if e1 := coll.Insert(recs[0]); e1 != nil { - return e1 - } - if e2 := coll.Insert(recs[1]); e2 != nil { - return e2 - } - return nil - }) - require.NoError(t, err) - - r, err := ms.Get("site1") - assert.NoError(t, err) - assert.Equal(t, "secret1", r) - - r, err = ms.Get("site2") - assert.NoError(t, err) - assert.Equal(t, "secret2", r) - - _, err = ms.Get("no-site-in-db") - assert.Error(t, err, "can't get secret for site no-site-in-db") -} diff --git a/backend/app/store/service/service.go b/backend/app/store/service/service.go index 8283d5b1..2d0ae63a 100644 --- a/backend/app/store/service/service.go +++ b/backend/app/store/service/service.go @@ -6,18 +6,16 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" - "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store/engine" - "github.com/umputun/remark/backend/app/store/keys" ) // DataStore wraps store.Interface with additional methods type DataStore struct { engine.Interface EditDuration time.Duration - KeyStore keys.Store AdminStore admin.Store MaxCommentSize int @@ -56,7 +54,7 @@ func (s *DataStore) prepareNewComment(comment store.Comment) (store.Comment, err } comment.Sanitize() // clear potentially dangerous js from all parts of comment - secret, err := s.KeyStore.Get(comment.Locator.SiteID) + secret, err := s.AdminStore.Key(comment.Locator.SiteID) if err != nil { return store.Comment{}, errors.Wrapf(err, "can't get secret for site %s", comment.Locator.SiteID) } diff --git a/backend/app/store/service/service_test.go b/backend/app/store/service/service_test.go index 645738ca..55442340 100644 --- a/backend/app/store/service/service_test.go +++ b/backend/app/store/service/service_test.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/umputun/remark/backend/app/store/keys" + "github.com/umputun/remark/backend/app/store/admin" "github.com/umputun/remark/backend/app/store" "github.com/umputun/remark/backend/app/store/engine" @@ -23,8 +23,8 @@ var testDb = "/tmp/test-remark.db" func TestService_CreateFromEmpty(t *testing.T) { defer os.Remove(testDb) - ks := keys.NewStaticStore("secret 123") - b := DataStore{Interface: prepStoreEngine(t), KeyStore: ks} + ks := admin.NewStaticKeyStore("secret 123") + b := DataStore{Interface: prepStoreEngine(t), AdminStore: ks} comment := store.Comment{ Text: "text", User: store.User{IP: "192.168.1.1", ID: "user", Name: "name"}, @@ -47,8 +47,8 @@ func TestService_CreateFromEmpty(t *testing.T) { func TestService_CreateFromPartial(t *testing.T) { defer os.Remove(testDb) - ks := keys.NewStaticStore("secret 123") - b := DataStore{Interface: prepStoreEngine(t), KeyStore: ks} + ks := admin.NewStaticKeyStore("secret 123") + b := DataStore{Interface: prepStoreEngine(t), AdminStore: ks} comment := store.Comment{ Text: "text", Timestamp: time.Date(2018, 3, 25, 16, 34, 33, 0, time.UTC), @@ -73,7 +73,7 @@ func TestService_CreateFromPartial(t *testing.T) { func TestService_Vote(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")} comment := store.Comment{ Text: "text", @@ -118,7 +118,7 @@ func TestService_Vote(t *testing.T) { func TestService_VoteAggressive(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")} comment := store.Comment{ Text: "text", @@ -178,7 +178,7 @@ func TestService_VoteAggressive(t *testing.T) { func TestService_VoteConcurrent(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")} comment := store.Comment{ Text: "text", @@ -209,7 +209,7 @@ func TestService_VoteConcurrent(t *testing.T) { func TestService_Pin(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")} res, err := b.Last("radio-t", 0) t.Logf("%+v", res[0]) @@ -233,7 +233,7 @@ func TestService_Pin(t *testing.T) { func TestService_EditComment(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")} res, err := b.Last("radio-t", 0) t.Logf("%+v", res[0]) @@ -260,7 +260,7 @@ func TestService_EditComment(t *testing.T) { func TestService_DeleteComment(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")} res, err := b.Last("radio-t", 0) t.Logf("%+v", res[0]) @@ -279,7 +279,7 @@ func TestService_DeleteComment(t *testing.T) { func TestService_EditCommentDurationFailed(t *testing.T) { defer os.Remove(testDb) - b := DataStore{Interface: prepStoreEngine(t), EditDuration: 100 * time.Millisecond, KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{Interface: prepStoreEngine(t), EditDuration: 100 * time.Millisecond, AdminStore: admin.NewStaticKeyStore("secret 123")} res, err := b.Last("radio-t", 0) t.Logf("%+v", res[0]) @@ -296,7 +296,7 @@ func TestService_EditCommentDurationFailed(t *testing.T) { func TestService_ValidateComment(t *testing.T) { - b := DataStore{MaxCommentSize: 2000, KeyStore: keys.NewStaticStore("secret 123")} + b := DataStore{MaxCommentSize: 2000, AdminStore: admin.NewStaticKeyStore("secret 123")} longText := fmt.Sprintf("%4000s", "X") tbl := []struct {