Merge pull request #280 from umputun/anon

add anon option and direct provider #279
This commit is contained in:
Umputun
2019-02-19 14:10:26 -06:00
committed by GitHub
3 changed files with 73 additions and 5 deletions
+6
View File
@@ -116,6 +116,7 @@ _this is the recommended way to run remark42_
| auth.yandex.cid | AUTH_YANDEX_CID | | Yandex OAuth client ID |
| auth.yandex.csec | AUTH_YANDEX_CSEC | | Yandex OAuth client secret |
| auth.dev | AUTH_DEV | `false` | local oauth2 server, development mode only |
| auth.anon | AUTH_ANON | `false` | enable anonymous login |
| notify.type | NOTIFY_TYPE | none | type of notification (none or telegram) |
| notify.queue | NOTIFY_QUEUE | `100` | size of notification queue |
| notify.telegram.token | NOTIFY_TELEGRAM_TOKEN | | telegram token |
@@ -475,6 +476,11 @@ type User struct {
_currently supported providers are `google`, `facebook`, `github` and `yandex`_
Optionally, anonymous access can be turned on. In this case and extra `anonymous` provider will allow logins without any social login with any name satisfying 2 conditions:
- name should be at least 3 characters long
- name has to start from the letter and contains letters, numbers, underscores and spaces only.
### Commenting
* `POST /api/v1/comment` - add a comment. _auth required_
+25 -5
View File
@@ -8,6 +8,7 @@ import (
"os"
"os/signal"
"path"
"regexp"
"strings"
"syscall"
"time"
@@ -66,11 +67,12 @@ type ServerCommand struct {
JWT time.Duration `long:"jwt" env:"JWT" default:"5m" description:"jwt TTL"`
Cookie time.Duration `long:"cookie" env:"COOKIE" default:"200h" description:"auth cookie TTL"`
} `group:"ttl" namespace:"ttl" env-namespace:"TTL"`
Google AuthGroup `group:"google" namespace:"google" env-namespace:"GOOGLE" description:"Google OAuth"`
Github AuthGroup `group:"github" namespace:"github" env-namespace:"GITHUB" description:"Github OAuth"`
Facebook AuthGroup `group:"facebook" namespace:"facebook" env-namespace:"FACEBOOK" description:"Facebook OAuth"`
Yandex AuthGroup `group:"yandex" namespace:"yandex" env-namespace:"YANDEX" description:"Yandex OAuth"`
Dev bool `long:"dev" env:"DEV" description:"enable dev (local) oauth2"`
Google AuthGroup `group:"google" namespace:"google" env-namespace:"GOOGLE" description:"Google OAuth"`
Github AuthGroup `group:"github" namespace:"github" env-namespace:"GITHUB" description:"Github OAuth"`
Facebook AuthGroup `group:"facebook" namespace:"facebook" env-namespace:"FACEBOOK" description:"Facebook OAuth"`
Yandex AuthGroup `group:"yandex" namespace:"yandex" env-namespace:"YANDEX" description:"Yandex OAuth"`
Dev bool `long:"dev" env:"DEV" description:"enable dev (local) oauth2"`
Anonymous bool `long:"anon" env:"ANON" description:"enable anonymous login"`
} `group:"auth" namespace:"auth" env-namespace:"AUTH"`
CommonOpts
@@ -477,6 +479,24 @@ func (s *ServerCommand) addAuthProviders(authenticator *auth.Service) {
providers++
}
if s.Auth.Anonymous {
log.Print("[INFO] anonymous access enabled")
var isValidAnonName = regexp.MustCompile(`^[a-zA-Z][\w ]+$`).MatchString
authenticator.AddDirectProvider("anonymous", provider.CredCheckerFunc(func(user, _ string) (ok bool, err error) {
user = strings.TrimSpace(user)
if len(user) < 3 {
log.Printf("[WARN] name %q is too short, should be at least 3 characters", user)
return false, nil
}
if !isValidAnonName(user) {
log.Printf("[WARN] name %q should have letters, digits, underscores and spaces only", user)
return false, nil
}
return true, nil
}))
}
if providers == 0 {
log.Printf("[WARN] no auth providers defined")
}
+42
View File
@@ -83,6 +83,48 @@ func TestServerApp_DevMode(t *testing.T) {
app.Wait()
}
func TestServerApp_AnonMode(t *testing.T) {
app, ctx := prepServerApp(t, 500*time.Millisecond, func(o ServerCommand) ServerCommand {
o.Port = 18085
o.Auth.Anonymous = true
return o
})
go func() { _ = app.run(ctx) }()
time.Sleep(100 * time.Millisecond) // let server start
assert.Equal(t, 4+1, len(app.restSrv.Authenticator.Providers()), "extra auth provider for anon")
assert.Equal(t, "anonymous", app.restSrv.Authenticator.Providers()[4].Name(), "anon auth provider")
// send ping
resp, err := http.Get("http://localhost:18085/api/v1/ping")
require.Nil(t, err)
defer resp.Body.Close()
assert.Equal(t, 200, resp.StatusCode)
body, err := ioutil.ReadAll(resp.Body)
assert.Nil(t, err)
assert.Equal(t, "pong", string(body))
// try to login with good name
resp, err = http.Get("http://localhost:18085/auth/anonymous/login?user=blah123&aud=remark42")
require.Nil(t, err)
defer resp.Body.Close()
assert.Equal(t, 200, resp.StatusCode)
// try to login with bad name
resp, err = http.Get("http://localhost:18085/auth/anonymous/login?user=**blah123&aud=remark42")
require.Nil(t, err)
defer resp.Body.Close()
assert.Equal(t, 403, resp.StatusCode)
// try to login with short name
resp, err = http.Get(`http://localhost:18085/auth/anonymous/login?user=bl%20%20&aud=remark42`)
require.Nil(t, err)
defer resp.Body.Close()
assert.Equal(t, 403, resp.StatusCode)
app.Wait()
}
func TestServerApp_WithMongo(t *testing.T) {
mongoURL := os.Getenv("MONGO_TEST")