go vendor
This commit is contained in:
6
vendor/github.com/revel/modules/auth/README.md
generated
vendored
Normal file
6
vendor/github.com/revel/modules/auth/README.md
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
modules/auth
|
||||
===============
|
||||
|
||||
Basic user/auth module
|
||||
|
||||
This should be modeled after [flask-security](https://github.com/mattupstate/flask-security)
|
78
vendor/github.com/revel/modules/auth/auth.go
generated
vendored
Normal file
78
vendor/github.com/revel/modules/auth/auth.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
// "errors"
|
||||
)
|
||||
|
||||
var (
|
||||
Store StorageDriver
|
||||
)
|
||||
|
||||
// Store = gormauth.NewGormAuthDriver()
|
||||
|
||||
type UserAuth interface {
|
||||
// getters/setters implemented by the app-level model
|
||||
UserId() string
|
||||
Secret() string
|
||||
HashedSecret() string
|
||||
SetHashedSecret(string)
|
||||
|
||||
SecretDriver
|
||||
// // implemented by secret driver
|
||||
// Authenticate() (bool, error)
|
||||
}
|
||||
|
||||
type SecretDriver interface {
|
||||
Authenticate() (bool, error)
|
||||
HashSecret(args ...interface{}) (string, error)
|
||||
|
||||
// stuff for documentation
|
||||
// UserContext is expected in these?
|
||||
|
||||
// Secret expects 0 or non-0 arguments
|
||||
// When no parameter is passed, it acts as a getter
|
||||
// When one or more parameters are passed, it acts as a setter
|
||||
// A driver should specify the expected arguments and their meanings
|
||||
|
||||
// Register()
|
||||
// Login()
|
||||
// Logout()
|
||||
}
|
||||
|
||||
type StorageDriver interface {
|
||||
Save(user interface{}) error
|
||||
// Load should take a partially filled struct
|
||||
// (with values needed to look up)
|
||||
// and fills in the rest
|
||||
Load(user interface{}) error
|
||||
}
|
||||
|
||||
// func init() {
|
||||
// // auth.Store = gorm...
|
||||
// }
|
||||
|
||||
// func (c App) Login(email, password string) {
|
||||
|
||||
// u := User {
|
||||
// Email ...
|
||||
// }
|
||||
|
||||
// good, err := auth.Authenticate(email, password)
|
||||
|
||||
// user, err := user_info.GetUserByEmail(email)
|
||||
// }
|
||||
|
||||
// Bycrypt Authenticate() expects a single string argument of the plaintext password
|
||||
// It returns true on success and false if error or password mismatch
|
||||
// func Authenticate(attemptedUser UserAuth) (bool, error) {
|
||||
// // check user in Store
|
||||
// loadedUser, err := Store.Load(attemptedUser.UserId())
|
||||
// if err != nil {
|
||||
// return false, errors.New("User Not Found")
|
||||
// }
|
||||
|
||||
// loadedUser.Authenticate(attemptedUser.Secret())
|
||||
|
||||
// // successfully authenticated
|
||||
// return true, nil
|
||||
// }
|
134
vendor/github.com/revel/modules/auth/auth_test.go
generated
vendored
Normal file
134
vendor/github.com/revel/modules/auth/auth_test.go
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/modules/auth"
|
||||
"github.com/revel/modules/auth/driver/secret"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
email string
|
||||
password string
|
||||
hashpass string
|
||||
|
||||
secret.BcryptAuth // SecurityDriver for testing
|
||||
}
|
||||
|
||||
func NewUser(email, pass string) *User {
|
||||
u := &User{
|
||||
email: email,
|
||||
password: pass,
|
||||
}
|
||||
u.UserContext = u
|
||||
return u
|
||||
}
|
||||
|
||||
func (self *User) UserId() string {
|
||||
return self.email
|
||||
}
|
||||
|
||||
func (self *User) Secret() string {
|
||||
return self.password
|
||||
}
|
||||
|
||||
func (self *User) HashedSecret() string {
|
||||
return self.hashpass
|
||||
}
|
||||
|
||||
func (self *User) SetHashedSecret(hpass string) {
|
||||
self.hashpass = hpass
|
||||
}
|
||||
|
||||
// func (self *User) Load() string
|
||||
|
||||
type TestStore struct {
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (self *TestStore) Save(user interface{}) error {
|
||||
u, ok := user.(*User)
|
||||
if !ok {
|
||||
return errors.New("TestStore.Save() expected arg of type User")
|
||||
}
|
||||
|
||||
hPass, err := u.HashSecret(u.Secret())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.data[u.UserId()] = hPass
|
||||
|
||||
return nil
|
||||
}
|
||||
func (self *TestStore) Load(user interface{}) error {
|
||||
u, ok := user.(*User)
|
||||
if !ok {
|
||||
return errors.New("TestStore.Load() expected arg of type User")
|
||||
}
|
||||
|
||||
hpass, ok := self.data[u.UserId()]
|
||||
if !ok {
|
||||
return errors.New("Record Not Found")
|
||||
}
|
||||
u.SetHashedSecret(hpass)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPasswordHash(t *testing.T) {
|
||||
auth.Store = &TestStore{
|
||||
data: make(map[string]string),
|
||||
}
|
||||
u := NewUser("demo@domain.com", "demopass")
|
||||
fail := NewUser("demo@domain.com", "")
|
||||
|
||||
var err error
|
||||
u.hashpass, err = u.HashSecret(u.password)
|
||||
if err != nil {
|
||||
t.Errorf("Should have hashed password, get error: %v\n", err)
|
||||
}
|
||||
fail.hashpass, err = fail.HashSecret(fail.password)
|
||||
if err == nil {
|
||||
t.Errorf("Should have failed hashing\n")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticate(t *testing.T) {
|
||||
auth.Store = &TestStore{
|
||||
data: make(map[string]string),
|
||||
}
|
||||
|
||||
// user registered a long time ago
|
||||
u := NewUser("demo@domain.com", "demopass")
|
||||
err := auth.Store.Save(u)
|
||||
if err != nil {
|
||||
t.Errorf("Should have saved user: %v", err)
|
||||
}
|
||||
|
||||
// users now logging in
|
||||
pass := NewUser("demo@domain.com", "demopass")
|
||||
fail := NewUser("demo@domain.com", "invalid")
|
||||
|
||||
// valid user is now trying to login
|
||||
// check user in DB
|
||||
err = auth.Store.Load(pass)
|
||||
if err != nil {
|
||||
t.Errorf("Should have loaded pass user: %v\n", err)
|
||||
}
|
||||
// check credentials
|
||||
ok, err := pass.Authenticate()
|
||||
if !ok || err != nil {
|
||||
t.Errorf("Should have authenticated user")
|
||||
}
|
||||
|
||||
// invalid user is now trying to login
|
||||
err = auth.Store.Load(fail)
|
||||
if err != nil {
|
||||
t.Errorf("Should have loaded fail user")
|
||||
}
|
||||
// this should fail
|
||||
ok, err = fail.Authenticate()
|
||||
if ok || err != nil {
|
||||
t.Errorf("Should have failed to authenticate user: %v\n", err)
|
||||
}
|
||||
}
|
53
vendor/github.com/revel/modules/auth/casbin/README.md
generated
vendored
Normal file
53
vendor/github.com/revel/modules/auth/casbin/README.md
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
modules/casbin
|
||||
======
|
||||
|
||||
Casbin authz is an authorization middleware for [Revel](https://github.com/revel/revel), it's based on [https://github.com/casbin/casbin](https://github.com/casbin/casbin).
|
||||
|
||||
## Simple Example
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
||||
"github.com/casbin/casbin"
|
||||
"github.com/revel/revel"
|
||||
"github.com/revel/modules/auth/casbin"
|
||||
)
|
||||
|
||||
var adapter = casbinauth.NewAdapter(params)
|
||||
var enforcer = casbin.NewEnforcer("authz_model.conf", adapter)
|
||||
var casbinModule = casbinauth.NewCasbinModule(enforcer)
|
||||
|
||||
var testFilters = []revel.Filter{
|
||||
casbinModule.AuthzFilter,
|
||||
func(c *revel.Controller, fc []revel.Filter) {
|
||||
c.RenderHTML("OK.")
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
r, _ := http.NewRequest("GET", "/dataset1/resource1", nil)
|
||||
r.SetBasicAuth("alice", "123")
|
||||
w := httptest.NewRecorder()
|
||||
context := revel.NewGoContext(nil)
|
||||
context.Request.SetRequest(r)
|
||||
context.Response.SetResponse(w)
|
||||
c := revel.NewController(context)
|
||||
|
||||
testFilters[0](c, testFilters)
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
The authorization determines a request based on ``{subject, object, action}``, which means what ``subject`` can perform what ``action`` on what ``object``. In this plugin, the meanings are:
|
||||
|
||||
1. ``subject``: the logged-on user name
|
||||
2. ``object``: the URL path for the web resource like "dataset1/item1"
|
||||
3. ``action``: HTTP method like GET, POST, PUT, DELETE, or the high-level actions you defined like "read-file", "write-blog"
|
||||
|
||||
|
||||
For how to write authorization policy and other details, please refer to [the Casbin's documentation](https://github.com/casbin/casbin).
|
162
vendor/github.com/revel/modules/auth/casbin/adapter.go
generated
vendored
Normal file
162
vendor/github.com/revel/modules/auth/casbin/adapter.go
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
package casbinauthz
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/casbin/casbin/model"
|
||||
"github.com/casbin/casbin/persist"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/revel/modules/orm/gorm/app"
|
||||
)
|
||||
|
||||
type Line struct {
|
||||
PType string `gorm:"size:100"`
|
||||
V0 string `gorm:"size:100"`
|
||||
V1 string `gorm:"size:100"`
|
||||
V2 string `gorm:"size:100"`
|
||||
V3 string `gorm:"size:100"`
|
||||
V4 string `gorm:"size:100"`
|
||||
V5 string `gorm:"size:100"`
|
||||
}
|
||||
|
||||
// Adapter represents the Gorm adapter for policy storage.
|
||||
type Adapter struct {
|
||||
driverName string
|
||||
dataSourceName string
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewAdapter is the constructor for Adapter.
|
||||
func NewAdapter(params gormdb.DbInfo) *Adapter {
|
||||
a := &Adapter{}
|
||||
gormdb.InitDBWithParameters(params)
|
||||
a.db = gormdb.DB
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Adapter) createTable() {
|
||||
if a.db.HasTable(&Line{}) {
|
||||
return
|
||||
}
|
||||
|
||||
err := a.db.CreateTable(&Line{}).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Adapter) dropTable() {
|
||||
err := a.db.DropTable(&Line{}).Error
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadPolicyLine(line Line, model model.Model) {
|
||||
lineText := line.PType
|
||||
if line.V0 != "" {
|
||||
lineText += ", " + line.V0
|
||||
}
|
||||
if line.V1 != "" {
|
||||
lineText += ", " + line.V1
|
||||
}
|
||||
if line.V2 != "" {
|
||||
lineText += ", " + line.V2
|
||||
}
|
||||
if line.V3 != "" {
|
||||
lineText += ", " + line.V3
|
||||
}
|
||||
if line.V4 != "" {
|
||||
lineText += ", " + line.V4
|
||||
}
|
||||
if line.V5 != "" {
|
||||
lineText += ", " + line.V5
|
||||
}
|
||||
|
||||
persist.LoadPolicyLine(lineText, model)
|
||||
}
|
||||
|
||||
// LoadPolicy loads policy from database.
|
||||
func (a *Adapter) LoadPolicy(model model.Model) error {
|
||||
var lines []Line
|
||||
err := a.db.Find(&lines).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, line := range lines {
|
||||
loadPolicyLine(line, model)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func savePolicyLine(ptype string, rule []string) Line {
|
||||
line := Line{}
|
||||
|
||||
line.PType = ptype
|
||||
if len(rule) > 0 {
|
||||
line.V0 = rule[0]
|
||||
}
|
||||
if len(rule) > 1 {
|
||||
line.V1 = rule[1]
|
||||
}
|
||||
if len(rule) > 2 {
|
||||
line.V2 = rule[2]
|
||||
}
|
||||
if len(rule) > 3 {
|
||||
line.V3 = rule[3]
|
||||
}
|
||||
if len(rule) > 4 {
|
||||
line.V4 = rule[4]
|
||||
}
|
||||
if len(rule) > 5 {
|
||||
line.V5 = rule[5]
|
||||
}
|
||||
|
||||
return line
|
||||
}
|
||||
|
||||
// SavePolicy saves policy to database.
|
||||
func (a *Adapter) SavePolicy(model model.Model) error {
|
||||
a.dropTable()
|
||||
a.createTable()
|
||||
|
||||
for ptype, ast := range model["p"] {
|
||||
for _, rule := range ast.Policy {
|
||||
line := savePolicyLine(ptype, rule)
|
||||
err := a.db.Create(&line).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ptype, ast := range model["g"] {
|
||||
for _, rule := range ast.Policy {
|
||||
line := savePolicyLine(ptype, rule)
|
||||
err := a.db.Create(&line).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddPolicy adds a policy rule to the storage.
|
||||
func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// RemovePolicy removes a policy rule from the storage.
|
||||
func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
|
||||
func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
49
vendor/github.com/revel/modules/auth/casbin/authz.go
generated
vendored
Normal file
49
vendor/github.com/revel/modules/auth/casbin/authz.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package casbinauthz
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/casbin/casbin"
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
type CasbinModule struct {
|
||||
enforcer *casbin.Enforcer
|
||||
}
|
||||
|
||||
func NewCasbinModule(enforcer *casbin.Enforcer) *CasbinModule {
|
||||
cm := &CasbinModule{}
|
||||
cm.enforcer = enforcer
|
||||
return cm
|
||||
}
|
||||
|
||||
// AuthzFilter enables the authorization based on Casbin.
|
||||
//
|
||||
// Usage:
|
||||
// 1) Add `casbin.AuthzFilter` to the app's filters (it must come after the authentication).
|
||||
// 2) Init the Casbin enforcer.
|
||||
func (cm *CasbinModule) AuthzFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
if !CheckPermission(cm.enforcer, c.Request) {
|
||||
c.Result = c.Forbidden("Access denied by the Authz plugin.")
|
||||
return
|
||||
} else {
|
||||
fc[0](c, fc[1:])
|
||||
}
|
||||
}
|
||||
|
||||
// GetUserName gets the user name from the request.
|
||||
// Currently, only HTTP basic authentication is supported
|
||||
func GetUserName(r *revel.Request) string {
|
||||
req := r.In.GetRaw().(*http.Request)
|
||||
username, _, _ := req.BasicAuth()
|
||||
return username
|
||||
}
|
||||
|
||||
// CheckPermission checks the user/method/path combination from the request.
|
||||
// Returns true (permission granted) or false (permission forbidden)
|
||||
func CheckPermission(e *casbin.Enforcer, r *revel.Request) bool {
|
||||
user := GetUserName(r)
|
||||
method := r.Method
|
||||
path := r.URL.Path
|
||||
return e.Enforce(user, path, method)
|
||||
}
|
14
vendor/github.com/revel/modules/auth/casbin/authz_model.conf
generated
vendored
Normal file
14
vendor/github.com/revel/modules/auth/casbin/authz_model.conf
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
[policy_definition]
|
||||
p = sub, obj, act
|
||||
|
||||
[role_definition]
|
||||
g = _, _
|
||||
|
||||
[policy_effect]
|
||||
e = some(where (p.eft == allow))
|
||||
|
||||
[matchers]
|
||||
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
|
7
vendor/github.com/revel/modules/auth/casbin/authz_policy.csv
generated
vendored
Normal file
7
vendor/github.com/revel/modules/auth/casbin/authz_policy.csv
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
p, alice, /dataset1/*, GET
|
||||
p, alice, /dataset1/resource1, POST
|
||||
p, bob, /dataset2/resource1, *
|
||||
p, bob, /dataset2/resource2, GET
|
||||
p, bob, /dataset2/folder1/*, POST
|
||||
p, dataset1_admin, /dataset1/*, *
|
||||
g, cathy, dataset1_admin
|
|
129
vendor/github.com/revel/modules/auth/casbin/authz_test.go
generated
vendored
Normal file
129
vendor/github.com/revel/modules/auth/casbin/authz_test.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
package casbinauthz
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/casbin/casbin"
|
||||
"github.com/casbin/casbin/util"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/revel/revel"
|
||||
"github.com/revel/modules/orm/gorm/app"
|
||||
)
|
||||
|
||||
var adapter = NewAdapter(DefaultDbParams())
|
||||
var enforcer = casbin.NewEnforcer("authz_model.conf", adapter)
|
||||
var casbinModule = NewCasbinModule(enforcer)
|
||||
|
||||
var testFilters = []revel.Filter{
|
||||
casbinModule.AuthzFilter,
|
||||
func(c *revel.Controller, fc []revel.Filter) {
|
||||
c.RenderHTML("OK.")
|
||||
},
|
||||
}
|
||||
|
||||
func DefaultDbParams() gormdb.DbInfo {
|
||||
params := gormdb.DbInfo{}
|
||||
params.DbDriver = "mysql"
|
||||
params.DbHost = "(localhost:3306)"
|
||||
params.DbUser = "root"
|
||||
params.DbPassword = ""
|
||||
params.DbName = "casbin"
|
||||
return params
|
||||
}
|
||||
|
||||
func testRequest(t *testing.T, user string, path string, method string, code int) {
|
||||
r, _ := http.NewRequest(method, path, nil)
|
||||
r.SetBasicAuth(user, "123")
|
||||
w := httptest.NewRecorder()
|
||||
context := revel.NewGoContext(nil)
|
||||
context.Request.SetRequest(r)
|
||||
context.Response.SetResponse(w)
|
||||
c := revel.NewController(context)
|
||||
|
||||
testFilters[0](c, testFilters)
|
||||
|
||||
if c.Response.Status != code {
|
||||
t.Errorf("%s, %s, %s: %d, supposed to be %d", user, path, method, c.Response.Status, code)
|
||||
}
|
||||
}
|
||||
|
||||
func testGetPolicy(t *testing.T, e *casbin.Enforcer, res [][]string) {
|
||||
myRes := e.GetPolicy()
|
||||
log.Print("Policy: ", myRes)
|
||||
|
||||
if !util.Array2DEquals(res, myRes) {
|
||||
t.Error("Policy: ", myRes, ", supposed to be ", res)
|
||||
}
|
||||
}
|
||||
|
||||
func initPolicy(t *testing.T) {
|
||||
// Because the DB is empty at first,
|
||||
// so we need to load the policy from the file adapter (.CSV) first.
|
||||
e := casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")
|
||||
|
||||
a := NewAdapter(DefaultDbParams())
|
||||
// This is a trick to save the current policy to the DB.
|
||||
// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
|
||||
// The current policy means the policy in the Casbin enforcer (aka in memory).
|
||||
err := a.SavePolicy(e.GetModel())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
// Initialize some policy in DB.
|
||||
initPolicy(t)
|
||||
// Note: you don't need to look at the above code
|
||||
// if you already have a working DB with policy inside.
|
||||
|
||||
// Now the DB has policy, so we can provide a normal use case.
|
||||
|
||||
testRequest(t, "alice", "/dataset1/resource1", "GET", 200)
|
||||
testRequest(t, "alice", "/dataset1/resource1", "POST", 200)
|
||||
testRequest(t, "alice", "/dataset1/resource2", "GET", 200)
|
||||
testRequest(t, "alice", "/dataset1/resource2", "POST", 403)
|
||||
}
|
||||
|
||||
func TestPathWildcard(t *testing.T) {
|
||||
// Initialize some policy in DB.
|
||||
initPolicy(t)
|
||||
// Note: you don't need to look at the above code
|
||||
// if you already have a working DB with policy inside.
|
||||
|
||||
// Now the DB has policy, so we can provide a normal use case.
|
||||
|
||||
testRequest(t, "bob", "/dataset2/resource1", "GET", 200)
|
||||
testRequest(t, "bob", "/dataset2/resource1", "POST", 200)
|
||||
testRequest(t, "bob", "/dataset2/resource1", "DELETE", 200)
|
||||
testRequest(t, "bob", "/dataset2/resource2", "GET", 200)
|
||||
testRequest(t, "bob", "/dataset2/resource2", "POST", 403)
|
||||
testRequest(t, "bob", "/dataset2/resource2", "DELETE", 403)
|
||||
|
||||
testRequest(t, "bob", "/dataset2/folder1/item1", "GET", 403)
|
||||
testRequest(t, "bob", "/dataset2/folder1/item1", "POST", 200)
|
||||
testRequest(t, "bob", "/dataset2/folder1/item1", "DELETE", 403)
|
||||
testRequest(t, "bob", "/dataset2/folder1/item2", "GET", 403)
|
||||
testRequest(t, "bob", "/dataset2/folder1/item2", "POST", 200)
|
||||
testRequest(t, "bob", "/dataset2/folder1/item2", "DELETE", 403)
|
||||
}
|
||||
|
||||
func TestRBAC(t *testing.T) {
|
||||
// Initialize some policy in DB.
|
||||
initPolicy(t)
|
||||
// Note: you don't need to look at the above code
|
||||
// if you already have a working DB with policy inside.
|
||||
|
||||
// Now the DB has policy, so we can provide a normal use case.
|
||||
|
||||
// cathy can access all /dataset1/* resources via all methods because it has the dataset1_admin role.
|
||||
testRequest(t, "cathy", "/dataset1/item", "GET", 200)
|
||||
testRequest(t, "cathy", "/dataset1/item", "POST", 200)
|
||||
testRequest(t, "cathy", "/dataset1/item", "DELETE", 200)
|
||||
testRequest(t, "cathy", "/dataset2/item", "GET", 403)
|
||||
testRequest(t, "cathy", "/dataset2/item", "POST", 403)
|
||||
testRequest(t, "cathy", "/dataset2/item", "DELETE", 403)
|
||||
}
|
27
vendor/github.com/revel/modules/auth/doc.go
generated
vendored
Normal file
27
vendor/github.com/revel/modules/auth/doc.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/* A basic user authentication module for Revel
|
||||
|
||||
list of concerns:
|
||||
- Separating out the interface and driver
|
||||
- Removing DB/Storage dependency
|
||||
- UUID as default identifier?
|
||||
- how to deal with password/secret or generally, method of authorization
|
||||
- default {views,controllers,routes} for register/login/logut ?
|
||||
- reset password in most basic ?
|
||||
- activation (and other features) in a second / more sophisticated driver
|
||||
- filter for checking that user is authenticated
|
||||
|
||||
|
||||
I think a driver is made up of 2 parts
|
||||
data prep and data storage
|
||||
register and password reset are part of data prep
|
||||
as is the auth hash method
|
||||
they don't care how the data is stored
|
||||
|
||||
then there is the data store
|
||||
|
||||
perhaps each auth user model should instantiate 2 drivers instead of 1?
|
||||
one for data prep components and one for storage
|
||||
so the security driver and the storage driver
|
||||
|
||||
*/
|
||||
package auth
|
73
vendor/github.com/revel/modules/auth/driver/secret/bcrypt.go
generated
vendored
Normal file
73
vendor/github.com/revel/modules/auth/driver/secret/bcrypt.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/revel/modules/auth"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// example implementation of a Revel auth security driver
|
||||
// This driver should be embedded into your app-level User model
|
||||
// It expects your User model to have `Password` and `HashedPassword` string fields
|
||||
//
|
||||
// Your User model also needs to set itself as the UserContext for the BcryptAuth driver
|
||||
//
|
||||
// func NewUser(email, pass string) *User {
|
||||
// u := &User{
|
||||
// email: email,
|
||||
// password: pass,
|
||||
// }
|
||||
// u.UserContext = u
|
||||
// }
|
||||
//
|
||||
type BcryptAuth struct {
|
||||
UserContext auth.UserAuth
|
||||
}
|
||||
|
||||
// Bcrypt Secret() returns the hashed version of the password.
|
||||
// It expects an argument of type string, which is the plain text password
|
||||
func (self *BcryptAuth) HashSecret(args ...interface{}) (string, error) {
|
||||
if auth.Store == nil {
|
||||
return "", errors.New("Auth module StorageDriver not set")
|
||||
}
|
||||
argLen := len(args)
|
||||
if argLen == 0 {
|
||||
// we are getting
|
||||
return string(self.UserContext.HashedSecret()), nil
|
||||
}
|
||||
|
||||
if argLen == 1 {
|
||||
// we are setting
|
||||
password, ok := args[0].(string)
|
||||
if !ok {
|
||||
return "", errors.New("Wrong argument type provided, expected plaintext password as string")
|
||||
}
|
||||
hPass, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
self.UserContext.SetHashedSecret(string(hPass))
|
||||
return self.UserContext.HashedSecret(), nil
|
||||
}
|
||||
|
||||
// bad argument count
|
||||
return "", errors.New("Too many arguments provided, expected one")
|
||||
}
|
||||
|
||||
// Bycrypt Authenticate() expects a single string argument of the plaintext password
|
||||
// It returns true on success and false if error or password mismatch
|
||||
func (self *BcryptAuth) Authenticate() (bool, error) {
|
||||
// check password
|
||||
err := bcrypt.CompareHashAndPassword([]byte(self.UserContext.HashedSecret()), []byte(self.UserContext.Secret()))
|
||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// successfully authenticated
|
||||
return true, nil
|
||||
}
|
3
vendor/github.com/revel/modules/auth/driver/storage/mysql/README.md
generated
vendored
Normal file
3
vendor/github.com/revel/modules/auth/driver/storage/mysql/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
Mysql Auth driver
|
||||
==================
|
||||
|
3
vendor/github.com/revel/modules/auth/driver/storage/postgres/README.md
generated
vendored
Normal file
3
vendor/github.com/revel/modules/auth/driver/storage/postgres/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
Postgresql Auth driver
|
||||
==================
|
||||
|
3
vendor/github.com/revel/modules/auth/driver/storage/sqlite/README.md
generated
vendored
Normal file
3
vendor/github.com/revel/modules/auth/driver/storage/sqlite/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
Sqlite Auth driver
|
||||
==================
|
||||
|
17
vendor/github.com/revel/modules/auth/user.go
generated
vendored
Normal file
17
vendor/github.com/revel/modules/auth/user.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package auth
|
||||
|
||||
// var storageDriver auth.StorageDriver // postgres in example
|
||||
|
||||
// type AuthUserModel struct {
|
||||
// userId string
|
||||
// security *SecurityDriver // bcrypt in example
|
||||
|
||||
// }
|
||||
|
||||
// func (self *AuthUserModel) UserId() string {
|
||||
// return self.userId
|
||||
// }
|
||||
|
||||
// func (self *AuthUserModel) Secret() string {
|
||||
// return self.security.Secret()
|
||||
// }
|
Reference in New Issue
Block a user