diff --git a/README.md b/README.md index ff42ece3..4ee19883 100644 --- a/README.md +++ b/README.md @@ -110,10 +110,10 @@ _this is the recommended way to run remark42_ | store.bolt.path | STORE_BOLT_PATH | `./var` | path to data directory | | store.bolt.timeout | STORE_BOLT_TIMEOUT | `30s` | boltdb access timeout | | admin.shared.id | ADMIN_SHARED_ID | | admin names (list of user ids), _multi_ | -| admin.shared.email | ADMIN_SHARED_EMAIL | `admin@${REMARK_URL}` | admin email | +| admin.shared.email | ADMIN_SHARED_EMAIL | `admin@${REMARK_URL}` | admin emails, _multi_ | | backup | BACKUP_PATH | `./var/backup` | backups location | | max-back | MAX_BACKUP_FILES | `10` | max backup files to keep | -| cache.type | CACHE_TYPE | `mem` | type of cache, `redis_pub_sub` or `mem` or `none` | +| cache.type | CACHE_TYPE | `mem` | type of cache, `redis_pub_sub` or `mem` or `none` | | cache.redis_addr | CACHE_REDIS_ADDR | `127.0.0.1:6379` | address of redis PubSub instance, turn `redis_pub_sub` cache on for distributed cache | | cache.max.items | CACHE_MAX_ITEMS | `1000` | max number of cached items, `0` - unlimited | | cache.max.value | CACHE_MAX_VALUE | `65536` | max size of cached value, `0` - unlimited | diff --git a/backend/app/cmd/server.go b/backend/app/cmd/server.go index 34943696..4aaf403a 100644 --- a/backend/app/cmd/server.go +++ b/backend/app/cmd/server.go @@ -176,7 +176,7 @@ type AdminGroup struct { Type string `long:"type" env:"TYPE" description:"type of admin store" choice:"shared" choice:"rpc" default:"shared"` //nolint Shared struct { Admins []string `long:"id" env:"ID" description:"admin(s) ids" env-delim:","` - Email string `long:"email" env:"EMAIL" default:"" description:"admin email"` + Email []string `long:"email" env:"EMAIL" description:"admin emails" env-delim:","` } `group:"shared" namespace:"shared" env-namespace:"SHARED"` RPC RPCGroup `group:"rpc" namespace:"rpc" env-namespace:"RPC"` } @@ -457,8 +457,7 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) { ProxyCORS: s.ProxyCORS, } - // enable admin notifications only if admin email is set - if s.Notify.Email.AdminNotifications && s.Admin.Shared.Email != "" { + if s.Notify.Email.AdminNotifications { srv.AdminEmail = s.Admin.Shared.Email } @@ -652,12 +651,15 @@ func (s *ServerCommand) makeAdminStore() (admin.Store, error) { switch s.Admin.Type { case "shared": - if s.Admin.Shared.Email == "" { // no admin email, use admin@domain + sharedAdminEmail := "" + if len(s.Admin.Shared.Email) == 0 { // no admin email, use admin@domain if u, err := url.Parse(s.RemarkURL); err == nil { - s.Admin.Shared.Email = "admin@" + u.Host + sharedAdminEmail = "admin@" + u.Host } + } else { + sharedAdminEmail = s.Admin.Shared.Email[0] } - return admin.NewStaticStore(s.SharedSecret, s.Sites, s.Admin.Shared.Admins, s.Admin.Shared.Email), nil + return admin.NewStaticStore(s.SharedSecret, s.Sites, s.Admin.Shared.Admins, sharedAdminEmail), nil case "rpc": r := &admin.RPC{Client: jrpc.Client{ API: s.Admin.RPC.API, @@ -893,8 +895,8 @@ func (s *ServerCommand) makeSSLConfig() (config api.SSLConfig, err error) { config.ACMELocation = s.SSL.ACMELocation if s.SSL.ACMEEmail != "" { config.ACMEEmail = s.SSL.ACMEEmail - } else if s.Admin.Type == "shared" && s.Admin.Shared.Email != "" { - config.ACMEEmail = s.Admin.Shared.Email + } else if s.Admin.Type == "shared" && len(s.Admin.Shared.Email) != 0 { + config.ACMEEmail = s.Admin.Shared.Email[0] } else if u, e := url.Parse(s.RemarkURL); e == nil { config.ACMEEmail = "admin@" + u.Hostname() } diff --git a/backend/app/rest/api/rest.go b/backend/app/rest/api/rest.go index d34a46e8..41720975 100644 --- a/backend/app/rest/api/rest.go +++ b/backend/app/rest/api/rest.go @@ -51,7 +51,7 @@ type Rest struct { AnonVote bool WebRoot string RemarkURL string - AdminEmail string + AdminEmail []string ReadOnlyAge int SharedSecret string ScoreThresholds struct { diff --git a/backend/app/rest/api/rest_private.go b/backend/app/rest/api/rest_private.go index 808b778a..b21199ec 100644 --- a/backend/app/rest/api/rest_private.go +++ b/backend/app/rest/api/rest_private.go @@ -40,7 +40,7 @@ type private struct { notifyService *notify.Service authenticator *auth.Service remarkURL string - adminEmail string + adminEmail []string anonVote bool templates templates.FileReader } @@ -119,13 +119,13 @@ func (s *private) createCommentCtrl(w http.ResponseWriter, r *http.Request) { s.cache.Flush(cache.Flusher(comment.Locator.SiteID). Scopes(comment.Locator.URL, lastCommentsScope, comment.User.ID, comment.Locator.SiteID)) - // user notification if s.notifyService != nil { + // user notification s.notifyService.Submit(notify.Request{Comment: finalComment}) - } - // admin notification - if s.notifyService != nil && s.adminEmail != "" { - s.notifyService.Submit(notify.Request{Comment: finalComment, Email: s.adminEmail, ForAdmin: true}) + // admin notification + for _, adminEmail := range s.adminEmail { + s.notifyService.Submit(notify.Request{Comment: finalComment, Email: adminEmail, ForAdmin: true}) + } } log.Printf("[DEBUG] created commend %+v", finalComment) diff --git a/backend/app/rest/api/rest_test.go b/backend/app/rest/api/rest_test.go index 5285782f..8ffdd101 100644 --- a/backend/app/rest/api/rest_test.go +++ b/backend/app/rest/api/rest_test.go @@ -381,7 +381,7 @@ func startupT(t *testing.T) (ts *httptest.Server, srv *Rest, teardown func()) { Cache: memCache, WebRoot: tmp, RemarkURL: "https://demo.remark42.com", - AdminEmail: "admin@example.org", + AdminEmail: []string{"admin@example.org"}, ImageService: image.NewService(&image.FileSystem{ Location: tmp + "/pics-remark42", Partitions: 100,