add params config, more param tests
This commit is contained in:
@@ -32,10 +32,11 @@ Remark42 is a self-hosted, lightweight, and simple (yet functional) comment engi
|
||||
|
||||
| Command line | Environment | Default | Multi | Description |
|
||||
| ----------------- | -------------------- | ---------------------- | ----- | ---------------------------------------------- |
|
||||
| --url | REMARK_URL | `https://remark42.com` | no | url to remark server |
|
||||
| --url | REMARK_URL | | no | url to remark42 server |
|
||||
| --bolt | BOLTDB_PATH | `./var` | no | path to data directory |
|
||||
| --site | SITE | `remark` | yes | site name(s) |
|
||||
| --admin | ADMIN | | yes | admin names (list of user ids) |
|
||||
| --admin-email | ADMIN_EMAIL | `admin@${REMARK_URL}` | no | admin email |
|
||||
| --backup | BACKUP_PATH | `./var/backup` | no | backups location |
|
||||
| --max-back | MAX_BACKUP_FILES | `10` | no | max backup files to keep |
|
||||
| --max-cache-items | MAX_CACHE_ITEMS | `1000` | no | max number of cached items, `0` - unlimited |
|
||||
@@ -58,9 +59,35 @@ Remark42 is a self-hosted, lightweight, and simple (yet functional) comment engi
|
||||
| --dbg | DEBUG | `false` | no | debug mode |
|
||||
| --dev-passwd | DEV_PASSWD | | no | password for `dev` user |
|
||||
|
||||
##### Required parameters
|
||||
|
||||
**user has to provide secret key, can be any long and hard-to-guess string.**
|
||||
Most of the parameters have sane defaults and don't require customization. There are only a few parameters user has to define:
|
||||
|
||||
1. `SECRET` - secret key, can be any long and hard-to-guess string.
|
||||
1. `REMARK_URL` - url pointing to your remark42 server, i.e. `https://demo.reamark42.com`
|
||||
1. At least one pair of `REMARK_<PROVIDER>_CID` and `REMARK_<PROVIDER>_CSEC` defining oauth2 provider(s)
|
||||
|
||||
The minimal `docker-compose.yml` has to include all required parameters:
|
||||
|
||||
```yaml
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
remark:
|
||||
image: umputun/remark:master
|
||||
restart: always
|
||||
|
||||
environment:
|
||||
- REMARK_URL=https://demo.remark42.com # url pointing to your remark42 server
|
||||
- USER=1001 # UID on the host machine
|
||||
- SECRET=abcd-123456-xyz-$%^& # secret key
|
||||
- REMARK_GITHUB_CID=12345667890 # oauth2 client ID
|
||||
- REMARK_GITHUB_CSEC=abcdefg12345678 # oauth2 client secret
|
||||
volumes:
|
||||
- ./var:/srv/var # persistent volume to store all remark42 data
|
||||
```
|
||||
|
||||
|
||||
_all multi parameters separated by `,` in environment or repeated with command line key, like `--site=s1 --site=s2 ...`_
|
||||
|
||||
#### Register oauth2 providers
|
||||
@@ -426,8 +453,8 @@ _all admin calls require auth and admin privilege_
|
||||
* There is no cross-site login, i.e., user's behavior can't be analyzed across independent sites running remark42.
|
||||
* There are no third-party analytic services involved.
|
||||
* User can request all information remark42 knows about and export to gz file.
|
||||
* Supported complete cleanup of all information related to user activity.
|
||||
* Cookie lifespan can be restricted to session-only
|
||||
* Supported complete cleanup of all information related to user activity on demand.
|
||||
* Cookie lifespan can be restricted to session-only.
|
||||
* All potentially sensitive data stored by remark42 hashed and encrypted.
|
||||
|
||||
|
||||
@@ -435,11 +462,11 @@ _all admin calls require auth and admin privilege_
|
||||
|
||||
* Data stored in [boltdb](https://github.com/coreos/bbolt) (embedded key/value database) files under `BOLTDB_PATH`
|
||||
* Each site stored in a separate boltbd file.
|
||||
* In order to migrate/move remark42 to another host boltbd files should be transferred.
|
||||
* In order to migrate/move remark42 to another host boltbd files as well as avatars directory `AVATAR_STORE` should be transferred.
|
||||
* Automatic backup process runs every 24h and exports all content in json-like format to `backup-remark-YYYYMMDD.gz`.
|
||||
* Authentication implemented with [jwt](https://github.com/dgrijalva/jwt-go) stored in a cookie. It uses HttpOnly, secure cookies.
|
||||
* All heavy REST calls cached internally, default expiration 4h
|
||||
* User's activity throttled globally (up to 1000 simultaneous requests) and limited locally (per user, up to 10 req/sec)
|
||||
* All heavy REST calls cached internally in LRU cache limited by `MAX_CACHE_ITEMS` and `MAX_CACHE_SIZE`.
|
||||
* User's activity throttled globally (up to 1000 simultaneous requests) and limited locally (per user, usually up to 10 req/sec)
|
||||
* Request timeout set to 60sec
|
||||
* Development mode (`--dev-password` set) allows to test remark42 without social login and with admin privileges. Adds basic-auth for username: `dev`, password: `${DEV_PASSWD}`. **should not be used in production deployment**
|
||||
* User can vote for the comment multiple times but only to change his/her vote. Double-voting not allowed.
|
||||
|
||||
+13
-5
@@ -30,7 +30,7 @@ import (
|
||||
type Opts struct {
|
||||
BoltPath string `long:"bolt" env:"BOLTDB_PATH" default:"./var" description:"parent dir for bolt files"`
|
||||
Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","`
|
||||
RemarkURL string `long:"url" env:"REMARK_URL" default:"https://remark42.com" description:"url to remark"`
|
||||
RemarkURL string `long:"url" env:"REMARK_URL" required:"true" description:"url to remark"`
|
||||
Admins []string `long:"admin" env:"ADMIN" description:"admin(s) names" env-delim:","`
|
||||
AdminEmail string `long:"admin-email" env:"ADMIN_EMAIL" default:"" description:"admin email"`
|
||||
DevPasswd string `long:"dev-passwd" env:"DEV_PASSWD" default:"" description:"development mode password"`
|
||||
@@ -111,8 +111,16 @@ func New(opts Opts) (*Application, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(opts.RemarkURL, "http://") && !strings.HasPrefix(opts.RemarkURL, "https://") {
|
||||
return nil, errors.Errorf("invalid remark42 url %s", opts.RemarkURL)
|
||||
}
|
||||
|
||||
boltStore, err := makeBoltStore(opts.Sites, opts.BoltPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataService := service.DataStore{
|
||||
Interface: makeBoltStore(opts.Sites, opts.BoltPath),
|
||||
Interface: boltStore,
|
||||
EditDuration: 5 * time.Minute,
|
||||
Secret: opts.SecretKey,
|
||||
MaxCommentSize: opts.MaxCommentSize,
|
||||
@@ -213,16 +221,16 @@ func (a *Application) activateBackup(ctx context.Context) {
|
||||
}
|
||||
|
||||
// makeBoltStore creates store for all sites
|
||||
func makeBoltStore(siteNames []string, path string) engine.Interface {
|
||||
func makeBoltStore(siteNames []string, path string) (engine.Interface, error) {
|
||||
sites := []engine.BoltSite{}
|
||||
for _, site := range siteNames {
|
||||
sites = append(sites, engine.BoltSite{SiteID: site, FileName: fmt.Sprintf("%s/%s.db", path, site)})
|
||||
}
|
||||
result, err := engine.NewBoltDB(bolt.Options{Timeout: 30 * time.Second}, sites...)
|
||||
if err != nil {
|
||||
log.Fatalf("[ERROR] can't initialize data store, %+v", err)
|
||||
return nil, errors.Wrap(err, "can't initialize data store")
|
||||
}
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// mkdir -p for all dirs
|
||||
|
||||
+21
-1
@@ -44,6 +44,24 @@ func TestApplication(t *testing.T) {
|
||||
app.Wait()
|
||||
}
|
||||
|
||||
func TestApplicationFailed(t *testing.T) {
|
||||
opts := Opts{}
|
||||
p := flags.NewParser(&opts, flags.Default)
|
||||
|
||||
// RO bolt location
|
||||
p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--bolt=/dev/null"})
|
||||
_, err := New(opts)
|
||||
assert.EqualError(t, err, "can't initialize data store: failed to make boltdb for /dev/null/remark.db: "+
|
||||
"open /dev/null/remark.db: not a directory")
|
||||
t.Log(err)
|
||||
|
||||
//p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--bolt=/tmp", "--backup=/not-writable"})
|
||||
//_, err = New(opts)
|
||||
//assert.EqualError(t, err, "can't initialize data store: failed to make boltdb for /dev/null/remark.db: "+
|
||||
// "open /dev/null/remark.db: not a directory")
|
||||
//t.Log(err)
|
||||
}
|
||||
|
||||
func TestApplicationShutdown(t *testing.T) {
|
||||
app, ctx := prepApp(t, 18090, 500*time.Millisecond)
|
||||
st := time.Now()
|
||||
@@ -53,7 +71,9 @@ func TestApplicationShutdown(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestApplicationMainSignal(t *testing.T) {
|
||||
os.Args = []string{"test", "--secret=123456", "--bolt=/tmp/xyz", "--backup=/tmp", "--avatars=/tmp", "--port=18100"}
|
||||
os.Args = []string{"test", "--secret=123456", "--bolt=/tmp/xyz", "--backup=/tmp", "--avatars=/tmp",
|
||||
"--port=18100", "--url=https://demo.remark42.com"}
|
||||
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
||||
|
||||
Reference in New Issue
Block a user