Add change password.
parent
e47a19ada6
commit
f683eabb7a
78
server.go
78
server.go
|
@ -283,6 +283,33 @@ type deleteDBUserCommand struct {
|
|||
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.
|
||||
func (s *Server) WriteSeries(u *ClusterAdmin, database string, series *protocol.Series) error {
|
||||
// TODO:
|
||||
|
@ -312,6 +339,8 @@ func (s *Server) processor(done chan struct{}) {
|
|||
err = s.applyCreateDBUser(m)
|
||||
case deleteDBUserMessageType:
|
||||
err = s.applyDeleteDBUser(m)
|
||||
case changePasswordMessageType:
|
||||
err = s.applyChangePassword(m)
|
||||
}
|
||||
|
||||
// Sync high water mark and errors for broadcast topic.
|
||||
|
@ -381,6 +410,13 @@ func (db *Database) CreateUser(username, password string, permissions []string)
|
|||
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.
|
||||
func (db *Database) DeleteUser(username string) error {
|
||||
c := &deleteDBUserCommand{
|
||||
|
@ -391,15 +427,6 @@ func (db *Database) DeleteUser(username string) error {
|
|||
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 {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
@ -414,6 +441,39 @@ func (db *Database) deleteUser(username string) error {
|
|||
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.
|
||||
type ShardSpace struct {
|
||||
// Unique name within database. Required.
|
||||
|
|
|
@ -4,9 +4,9 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"code.google.com/p/go.crypto/bcrypt"
|
||||
"github.com/influxdb/influxdb"
|
||||
"github.com/influxdb/influxdb/messaging"
|
||||
)
|
||||
|
@ -94,7 +94,7 @@ func TestServer_DropDatabase_ErrDatabaseNotFound(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure the server can create a new user.
|
||||
func TestServer_CreateUser(t *testing.T) {
|
||||
func TestDatabase_CreateUser(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
defer s.Close()
|
||||
|
||||
|
@ -112,13 +112,15 @@ func TestServer_CreateUser(t *testing.T) {
|
|||
// Verify that the user exists.
|
||||
if u := db.User("susy"); u == nil {
|
||||
t.Fatalf("user not found")
|
||||
} else if reflect.DeepEqual(u, nil) {
|
||||
t.Fatalf("user mismatch: %#v", u)
|
||||
} else if u.Name != "susy" {
|
||||
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.
|
||||
func TestServer_CreateUser_ErrUsernameRequired(t *testing.T) {
|
||||
func TestDatabase_CreateUser_ErrUsernameRequired(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
defer s.Close()
|
||||
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.
|
||||
func TestServer_CreateUser_ErrInvalidUsername(t *testing.T) {
|
||||
func TestDatabase_CreateUser_ErrInvalidUsername(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
defer s.Close()
|
||||
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.
|
||||
func TestServer_CreateUser_ErrDatabaseNotFound(t *testing.T) {
|
||||
func TestDatabase_CreateUser_ErrDatabaseNotFound(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
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.
|
||||
func TestServer_CreateUser_ErrUserExists(t *testing.T) {
|
||||
func TestDatabase_CreateUser_ErrUserExists(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
defer s.Close()
|
||||
|
||||
|
@ -184,7 +186,7 @@ func TestServer_CreateUser_ErrUserExists(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure the server can delete an existing user.
|
||||
func TestServer_DeleteUser(t *testing.T) {
|
||||
func TestDatabase_DeleteUser(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
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.
|
||||
func TestServer_DeleteUser_ErrUsernameRequired(t *testing.T) {
|
||||
func TestDatabase_DeleteUser_ErrUsernameRequired(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
defer s.Close()
|
||||
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.
|
||||
func TestServer_DeleteUser_ErrDatabaseNotFound(t *testing.T) {
|
||||
func TestDatabase_DeleteUser_ErrDatabaseNotFound(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
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.
|
||||
func TestServer_DeleteUser_ErrUserNotFound(t *testing.T) {
|
||||
func TestDatabase_DeleteUser_ErrUserNotFound(t *testing.T) {
|
||||
s := OpenServer(NewMessagingClient())
|
||||
defer s.Close()
|
||||
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.
|
||||
type Server struct {
|
||||
*influxdb.Server
|
||||
|
|
Loading…
Reference in New Issue