Add change password.
parent
e47a19ada6
commit
f683eabb7a
78
server.go
78
server.go
|
@ -283,6 +283,33 @@ type deleteDBUserCommand struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) applyChangePassword(m *messaging.Message) error {
|
||||||
|
var c changePasswordCommand
|
||||||
|
mustUnmarshal(m.Data, &c)
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
// Validate user.
|
||||||
|
if c.Username == "" {
|
||||||
|
return ErrUsernameRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the database.
|
||||||
|
db := s.databases[c.Database]
|
||||||
|
if s.databases[c.Database] == nil {
|
||||||
|
return ErrDatabaseNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.changePassword(c.Username, c.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
type changePasswordCommand struct {
|
||||||
|
Database string `json:"database"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
// WriteSeries writes series data to the broker.
|
// WriteSeries writes series data to the broker.
|
||||||
func (s *Server) WriteSeries(u *ClusterAdmin, database string, series *protocol.Series) error {
|
func (s *Server) WriteSeries(u *ClusterAdmin, database string, series *protocol.Series) error {
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -312,6 +339,8 @@ func (s *Server) processor(done chan struct{}) {
|
||||||
err = s.applyCreateDBUser(m)
|
err = s.applyCreateDBUser(m)
|
||||||
case deleteDBUserMessageType:
|
case deleteDBUserMessageType:
|
||||||
err = s.applyDeleteDBUser(m)
|
err = s.applyDeleteDBUser(m)
|
||||||
|
case changePasswordMessageType:
|
||||||
|
err = s.applyChangePassword(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync high water mark and errors for broadcast topic.
|
// Sync high water mark and errors for broadcast topic.
|
||||||
|
@ -381,6 +410,13 @@ func (db *Database) CreateUser(username, password string, permissions []string)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Database) saveUser(u *DBUser) error {
|
||||||
|
db.mu.Lock()
|
||||||
|
db.users[u.Name] = u
|
||||||
|
db.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteUser removes a user from the database.
|
// DeleteUser removes a user from the database.
|
||||||
func (db *Database) DeleteUser(username string) error {
|
func (db *Database) DeleteUser(username string) error {
|
||||||
c := &deleteDBUserCommand{
|
c := &deleteDBUserCommand{
|
||||||
|
@ -391,15 +427,6 @@ func (db *Database) DeleteUser(username string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveUser persists a user to the database.
|
|
||||||
func (db *Database) saveUser(u *DBUser) error {
|
|
||||||
db.mu.Lock()
|
|
||||||
db.users[u.Name] = u
|
|
||||||
db.mu.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteUser removes a user from the database.
|
|
||||||
func (db *Database) deleteUser(username string) error {
|
func (db *Database) deleteUser(username string) error {
|
||||||
db.mu.Lock()
|
db.mu.Lock()
|
||||||
defer db.mu.Unlock()
|
defer db.mu.Unlock()
|
||||||
|
@ -414,6 +441,39 @@ func (db *Database) deleteUser(username string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChangePassword changes the password for a user in the database.
|
||||||
|
func (db *Database) ChangePassword(username, newPassword string) error {
|
||||||
|
c := &changePasswordCommand{
|
||||||
|
Database: db.Name(),
|
||||||
|
Username: username,
|
||||||
|
Password: newPassword,
|
||||||
|
}
|
||||||
|
_, err := db.server.broadcast(changePasswordMessageType, c)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) changePassword(username, newPassword string) error {
|
||||||
|
db.mu.Lock()
|
||||||
|
defer db.mu.Unlock()
|
||||||
|
|
||||||
|
// Check that user exists.
|
||||||
|
u := db.users[username]
|
||||||
|
if u == nil {
|
||||||
|
return ErrUserNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the hash of the password.
|
||||||
|
hash, err := HashPassword(newPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user password hash.
|
||||||
|
u.Hash = string(hash)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ShardSpace represents a policy for creating new shards in a database.
|
// ShardSpace represents a policy for creating new shards in a database.
|
||||||
type ShardSpace struct {
|
type ShardSpace struct {
|
||||||
// Unique name within database. Required.
|
// Unique name within database. Required.
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.google.com/p/go.crypto/bcrypt"
|
||||||
"github.com/influxdb/influxdb"
|
"github.com/influxdb/influxdb"
|
||||||
"github.com/influxdb/influxdb/messaging"
|
"github.com/influxdb/influxdb/messaging"
|
||||||
)
|
)
|
||||||
|
@ -94,7 +94,7 @@ func TestServer_DropDatabase_ErrDatabaseNotFound(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server can create a new user.
|
// Ensure the server can create a new user.
|
||||||
func TestServer_CreateUser(t *testing.T) {
|
func TestDatabase_CreateUser(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
|
@ -112,13 +112,15 @@ func TestServer_CreateUser(t *testing.T) {
|
||||||
// Verify that the user exists.
|
// Verify that the user exists.
|
||||||
if u := db.User("susy"); u == nil {
|
if u := db.User("susy"); u == nil {
|
||||||
t.Fatalf("user not found")
|
t.Fatalf("user not found")
|
||||||
} else if reflect.DeepEqual(u, nil) {
|
} else if u.Name != "susy" {
|
||||||
t.Fatalf("user mismatch: %#v", u)
|
t.Fatalf("username mismatch: %v", u.Name)
|
||||||
|
} else if bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte("pass")) != nil {
|
||||||
|
t.Fatal("invalid password")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when creating a user without a name.
|
// Ensure the server returns an error when creating a user without a name.
|
||||||
func TestServer_CreateUser_ErrUsernameRequired(t *testing.T) {
|
func TestDatabase_CreateUser_ErrUsernameRequired(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
if err := s.CreateDatabase("foo"); err != nil {
|
if err := s.CreateDatabase("foo"); err != nil {
|
||||||
|
@ -130,7 +132,7 @@ func TestServer_CreateUser_ErrUsernameRequired(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when creating a user with an invalid name.
|
// Ensure the server returns an error when creating a user with an invalid name.
|
||||||
func TestServer_CreateUser_ErrInvalidUsername(t *testing.T) {
|
func TestDatabase_CreateUser_ErrInvalidUsername(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
if err := s.CreateDatabase("foo"); err != nil {
|
if err := s.CreateDatabase("foo"); err != nil {
|
||||||
|
@ -142,7 +144,7 @@ func TestServer_CreateUser_ErrInvalidUsername(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when creating a user after the db is dropped.
|
// Ensure the server returns an error when creating a user after the db is dropped.
|
||||||
func TestServer_CreateUser_ErrDatabaseNotFound(t *testing.T) {
|
func TestDatabase_CreateUser_ErrDatabaseNotFound(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
|
@ -164,7 +166,7 @@ func TestServer_CreateUser_ErrDatabaseNotFound(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when creating a duplicate user.
|
// Ensure the server returns an error when creating a duplicate user.
|
||||||
func TestServer_CreateUser_ErrUserExists(t *testing.T) {
|
func TestDatabase_CreateUser_ErrUserExists(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
|
@ -184,7 +186,7 @@ func TestServer_CreateUser_ErrUserExists(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server can delete an existing user.
|
// Ensure the server can delete an existing user.
|
||||||
func TestServer_DeleteUser(t *testing.T) {
|
func TestDatabase_DeleteUser(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
|
@ -206,7 +208,7 @@ func TestServer_DeleteUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when delete a user without a name.
|
// Ensure the server returns an error when delete a user without a name.
|
||||||
func TestServer_DeleteUser_ErrUsernameRequired(t *testing.T) {
|
func TestDatabase_DeleteUser_ErrUsernameRequired(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
s.CreateDatabase("foo")
|
s.CreateDatabase("foo")
|
||||||
|
@ -216,7 +218,7 @@ func TestServer_DeleteUser_ErrUsernameRequired(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when deleting a user after the db is dropped.
|
// Ensure the server returns an error when deleting a user after the db is dropped.
|
||||||
func TestServer_DeleteUser_ErrDatabaseNotFound(t *testing.T) {
|
func TestDatabase_DeleteUser_ErrDatabaseNotFound(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
|
@ -232,7 +234,7 @@ func TestServer_DeleteUser_ErrDatabaseNotFound(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the server returns an error when deleting a non-existent user.
|
// Ensure the server returns an error when deleting a non-existent user.
|
||||||
func TestServer_DeleteUser_ErrUserNotFound(t *testing.T) {
|
func TestDatabase_DeleteUser_ErrUserNotFound(t *testing.T) {
|
||||||
s := OpenServer(NewMessagingClient())
|
s := OpenServer(NewMessagingClient())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
s.CreateDatabase("foo")
|
s.CreateDatabase("foo")
|
||||||
|
@ -241,6 +243,28 @@ func TestServer_DeleteUser_ErrUserNotFound(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the server can change the password of a user.
|
||||||
|
func TestDatabase_ChangePassword(t *testing.T) {
|
||||||
|
s := OpenServer(NewMessagingClient())
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
// Create a database and user.
|
||||||
|
s.CreateDatabase("foo")
|
||||||
|
db := s.Database("foo")
|
||||||
|
if err := db.CreateUser("susy", "pass", nil); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if bcrypt.CompareHashAndPassword([]byte(db.User("susy").Hash), []byte("pass")) != nil {
|
||||||
|
t.Fatal("invalid initial password")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user password.
|
||||||
|
if err := db.ChangePassword("susy", "newpass"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if bcrypt.CompareHashAndPassword([]byte(db.User("susy").Hash), []byte("newpass")) != nil {
|
||||||
|
t.Fatal("invalid new password")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Server is a wrapping test struct for influxdb.Server.
|
// Server is a wrapping test struct for influxdb.Server.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
*influxdb.Server
|
*influxdb.Server
|
||||||
|
|
Loading…
Reference in New Issue