Support exporting SQL LOGIN and SQL TOKEN hashes
This commit is contained in:
parent
26b138b9b0
commit
20abadf41f
7 changed files with 60 additions and 37 deletions
|
@ -50,7 +50,12 @@ func (e *executor) executeDefineLogin(ctx context.Context, ast *sql.DefineLoginS
|
|||
|
||||
ast.Code = rand.New(128)
|
||||
|
||||
ast.Pass, _ = bcrypt.GenerateFromPassword(ast.Pass, bcrypt.DefaultCost)
|
||||
switch len(ast.Hash) {
|
||||
default:
|
||||
ast.Pass = ast.Hash
|
||||
case 0:
|
||||
ast.Pass, _ = bcrypt.GenerateFromPassword(ast.Pass, bcrypt.DefaultCost)
|
||||
}
|
||||
|
||||
switch ast.Kind {
|
||||
case sql.NAMESPACE:
|
||||
|
|
|
@ -30,6 +30,7 @@ func TestInfo(t *testing.T) {
|
|||
txt := `
|
||||
USE NS test DB test;
|
||||
DEFINE LOGIN test ON NAMESPACE PASSWORD "test";
|
||||
DEFINE LOGIN test ON NAMESPACE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO";
|
||||
DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "test";
|
||||
DEFINE DATABASE test;
|
||||
INFO FOR NAMESPACE;
|
||||
|
@ -41,24 +42,25 @@ func TestInfo(t *testing.T) {
|
|||
|
||||
res, err := Execute(setupKV(), txt, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldHaveLength, 9)
|
||||
So(res, ShouldHaveLength, 10)
|
||||
So(res[1].Status, ShouldEqual, "OK")
|
||||
So(res[2].Status, ShouldEqual, "OK")
|
||||
So(res[3].Status, ShouldEqual, "OK")
|
||||
So(res[4].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[4].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[4].Result[0]).Get("login.test").Data(), ShouldEqual, "DEFINE LOGIN test ON NAMESPACE PASSWORD ********")
|
||||
So(data.Consume(res[4].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[4].Result[0]).Get("token.test").Data(), ShouldEqual, "DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE ********")
|
||||
So(data.Consume(res[4].Result[0]).Get("database").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[4].Result[0]).Get("database.test").Data(), ShouldEqual, "DEFINE DATABASE test")
|
||||
So(res[5].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[5].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("login.test").Data(), ShouldEqual, `DEFINE LOGIN test ON NAMESPACE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO"`)
|
||||
So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("token.test").Data(), ShouldEqual, `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "test"`)
|
||||
So(data.Consume(res[5].Result[0]).Get("database").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("database.test").Data(), ShouldEqual, "DEFINE DATABASE test")
|
||||
So(res[6].Status, ShouldEqual, "OK")
|
||||
So(res[7].Status, ShouldEqual, "OK")
|
||||
So(res[8].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[8].Result[0]).Get("login").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[8].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[8].Result[0]).Get("database").Data(), ShouldHaveLength, 0)
|
||||
So(res[9].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[9].Result[0]).Get("login").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[9].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[9].Result[0]).Get("database").Data(), ShouldHaveLength, 0)
|
||||
|
||||
})
|
||||
|
||||
|
@ -69,6 +71,7 @@ func TestInfo(t *testing.T) {
|
|||
txt := `
|
||||
USE NS test DB test;
|
||||
DEFINE LOGIN test ON DATABASE PASSWORD "test";
|
||||
DEFINE LOGIN test ON DATABASE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO";
|
||||
DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "test";
|
||||
DEFINE SCOPE test;
|
||||
DEFINE TABLE test;
|
||||
|
@ -82,29 +85,30 @@ func TestInfo(t *testing.T) {
|
|||
|
||||
res, err := Execute(setupKV(), txt, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldHaveLength, 11)
|
||||
So(res, ShouldHaveLength, 12)
|
||||
So(res[1].Status, ShouldEqual, "OK")
|
||||
So(res[2].Status, ShouldEqual, "OK")
|
||||
So(res[3].Status, ShouldEqual, "OK")
|
||||
So(res[4].Status, ShouldEqual, "OK")
|
||||
So(res[5].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[5].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("login.test").Data(), ShouldEqual, "DEFINE LOGIN test ON DATABASE PASSWORD ********")
|
||||
So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("token.test").Data(), ShouldEqual, "DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE ********")
|
||||
So(data.Consume(res[5].Result[0]).Get("scope").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("scope.test").Data(), ShouldEqual, "DEFINE SCOPE test")
|
||||
So(data.Consume(res[5].Result[0]).Get("table").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[5].Result[0]).Get("table.test").Data(), ShouldEqual, "DEFINE TABLE test")
|
||||
So(res[6].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[6].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[6].Result[0]).Get("login.test").Data(), ShouldEqual, `DEFINE LOGIN test ON DATABASE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO"`)
|
||||
So(data.Consume(res[6].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[6].Result[0]).Get("token.test").Data(), ShouldEqual, `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "test"`)
|
||||
So(data.Consume(res[6].Result[0]).Get("scope").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[6].Result[0]).Get("scope.test").Data(), ShouldEqual, "DEFINE SCOPE test")
|
||||
So(data.Consume(res[6].Result[0]).Get("table").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[6].Result[0]).Get("table.test").Data(), ShouldEqual, "DEFINE TABLE test")
|
||||
So(res[7].Status, ShouldEqual, "OK")
|
||||
So(res[8].Status, ShouldEqual, "OK")
|
||||
So(res[9].Status, ShouldEqual, "OK")
|
||||
So(res[10].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[10].Result[0]).Get("login").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[10].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[10].Result[0]).Get("scope").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[10].Result[0]).Get("table").Data(), ShouldHaveLength, 0)
|
||||
So(res[11].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[11].Result[0]).Get("login").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[11].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[11].Result[0]).Get("scope").Data(), ShouldHaveLength, 0)
|
||||
So(data.Consume(res[11].Result[0]).Get("table").Data(), ShouldHaveLength, 0)
|
||||
|
||||
})
|
||||
|
||||
|
@ -127,7 +131,7 @@ func TestInfo(t *testing.T) {
|
|||
So(res[1].Status, ShouldEqual, "OK")
|
||||
So(res[2].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[3].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
|
||||
So(data.Consume(res[3].Result[0]).Get("token.test").Data(), ShouldEqual, "DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE ********")
|
||||
So(data.Consume(res[3].Result[0]).Get("token.test").Data(), ShouldEqual, `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "test"`)
|
||||
So(res[4].Status, ShouldEqual, "OK")
|
||||
So(res[5].Status, ShouldEqual, "OK")
|
||||
So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
|
||||
|
|
|
@ -305,6 +305,7 @@ type DefineLoginStatement struct {
|
|||
Kind Token
|
||||
User *Ident
|
||||
Pass []byte
|
||||
Hash []byte
|
||||
Code []byte
|
||||
}
|
||||
|
||||
|
|
15
sql/login.go
15
sql/login.go
|
@ -42,12 +42,21 @@ func (p *parser) parseDefineLoginStatement() (stmt *DefineLoginStatement, err er
|
|||
}
|
||||
}
|
||||
|
||||
if _, _, err := p.shouldBe(PASSWORD); err != nil {
|
||||
tok, _, err := p.shouldBe(PASSWORD, PASSHASH)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if stmt.Pass, err = p.parseBinary(); err != nil {
|
||||
return nil, err
|
||||
if is(tok, PASSWORD) {
|
||||
if stmt.Pass, err = p.parseBinary(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if is(tok, PASSHASH) {
|
||||
if stmt.Hash, err = p.parseBinary(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -2180,7 +2180,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE LOGIN test ON NAMESPACE`,
|
||||
err: "Found `` but expected `PASSWORD`",
|
||||
err: "Found `` but expected `PASSWORD, PASSHASH`",
|
||||
},
|
||||
{
|
||||
sql: `DEFINE LOGIN test ON NAMESPACE PASSWORD`,
|
||||
|
@ -2188,7 +2188,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE LOGIN test ON NAMESPACE PASSWORD "123456"`,
|
||||
str: `DEFINE LOGIN test ON NAMESPACE PASSWORD ********`,
|
||||
str: `DEFINE LOGIN test ON NAMESPACE PASSHASH "123456"`,
|
||||
res: &Query{Statements: []Statement{&DefineLoginStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Kind: NAMESPACE,
|
||||
|
@ -2198,7 +2198,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE LOGIN test ON DATABASE PASSWORD "123456"`,
|
||||
str: `DEFINE LOGIN test ON DATABASE PASSWORD ********`,
|
||||
str: `DEFINE LOGIN test ON DATABASE PASSHASH "123456"`,
|
||||
res: &Query{Statements: []Statement{&DefineLoginStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Kind: DATABASE,
|
||||
|
@ -2261,7 +2261,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "secret"`,
|
||||
str: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE ********`,
|
||||
str: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "secret"`,
|
||||
res: &Query{Statements: []Statement{&DefineTokenStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Kind: NAMESPACE,
|
||||
|
@ -2273,7 +2273,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "secret"`,
|
||||
str: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE ********`,
|
||||
str: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "secret"`,
|
||||
res: &Query{Statements: []Statement{&DefineTokenStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Kind: DATABASE,
|
||||
|
@ -2285,7 +2285,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "secret"`,
|
||||
str: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE ********`,
|
||||
str: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "secret"`,
|
||||
res: &Query{Statements: []Statement{&DefineTokenStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Kind: SCOPE,
|
||||
|
|
|
@ -92,7 +92,7 @@ func maybe(b bool, v ...interface{}) string {
|
|||
}
|
||||
|
||||
func binar(b []byte) string {
|
||||
return fmt.Sprintf(`"%s"`, b)
|
||||
return fmt.Sprintf("%q", b)
|
||||
}
|
||||
|
||||
func quote(s string) string {
|
||||
|
@ -321,9 +321,10 @@ func (this RemoveDatabaseStatement) String() string {
|
|||
}
|
||||
|
||||
func (this DefineLoginStatement) String() string {
|
||||
return print("DEFINE LOGIN %v ON %v PASSWORD ********",
|
||||
return print("DEFINE LOGIN %v ON %v PASSHASH %s",
|
||||
this.User,
|
||||
this.Kind,
|
||||
binar(this.Pass),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -335,10 +336,11 @@ func (this RemoveLoginStatement) String() string {
|
|||
}
|
||||
|
||||
func (this DefineTokenStatement) String() string {
|
||||
return print("DEFINE TOKEN %v ON %v TYPE %v VALUE ********",
|
||||
return print("DEFINE TOKEN %v ON %v TYPE %v VALUE %s",
|
||||
this.Name,
|
||||
maybe(this.Kind == SCOPE, print("%v %v", this.Kind, this.What), print("%v", this.Kind)),
|
||||
this.Type,
|
||||
binar(this.Code),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ const (
|
|||
OR
|
||||
ORDER
|
||||
PARALLEL
|
||||
PASSHASH
|
||||
PASSWORD
|
||||
PERMISSIONS
|
||||
PRIORITY
|
||||
|
@ -339,6 +340,7 @@ var tokens = [...]string{
|
|||
OR: "OR",
|
||||
ORDER: "ORDER",
|
||||
PARALLEL: "PARALLEL",
|
||||
PASSHASH: "PASSHASH",
|
||||
PASSWORD: "PASSWORD",
|
||||
PERMISSIONS: "PERMISSIONS",
|
||||
PRIORITY: "PRIORITY",
|
||||
|
|
Loading…
Reference in a new issue