Move Accountant behind an interface
This commit is contained in:
parent
c1267829ac
commit
dc2800fa54
4 changed files with 111 additions and 85 deletions
|
@ -29,7 +29,7 @@ type Server struct {
|
||||||
world *game.World
|
world *game.World
|
||||||
|
|
||||||
// Accountant
|
// Accountant
|
||||||
accountant *accounts.Accountant
|
accountant accounts.Accountant
|
||||||
|
|
||||||
// gRPC server
|
// gRPC server
|
||||||
netListener net.Listener
|
netListener net.Listener
|
||||||
|
@ -81,7 +81,7 @@ func NewServer(opts ...ServerOption) *Server {
|
||||||
persistence: EphemeralData,
|
persistence: EphemeralData,
|
||||||
schedule: cron.New(),
|
schedule: cron.New(),
|
||||||
world: game.NewWorld(32),
|
world: game.NewWorld(32),
|
||||||
accountant: accounts.NewAccountant(),
|
accountant: accounts.NewSimpleAccountant(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply all options
|
// Apply all options
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
package accounts
|
package accounts
|
||||||
|
|
||||||
import (
|
// Accountant decribes something that stores accounts and account values
|
||||||
"fmt"
|
type Accountant interface {
|
||||||
"time"
|
// RegisterAccount will register a new account and return it's info
|
||||||
|
RegisterAccount(name string) (acc Account, err error)
|
||||||
|
|
||||||
"github.com/google/uuid"
|
// AssignData stores a custom account key value pair
|
||||||
)
|
AssignData(account string, key string, value string) error
|
||||||
|
|
||||||
|
// GetValue returns custom account data for a specific key
|
||||||
|
GetValue(account string, key string) (string, error)
|
||||||
|
|
||||||
|
// VerifySecret will verify whether the account secret matches with the
|
||||||
|
VerifySecret(account string, secret string) (bool, error)
|
||||||
|
|
||||||
|
// GetSecret gets the secret associated with an account
|
||||||
|
GetSecret(account string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
// Account represents a registered user
|
// Account represents a registered user
|
||||||
type Account struct {
|
type Account struct {
|
||||||
|
@ -15,75 +26,3 @@ type Account struct {
|
||||||
// Data represents internal account data
|
// Data represents internal account data
|
||||||
Data map[string]string `json:"data"`
|
Data map[string]string `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accountant manages a set of accounts
|
|
||||||
type Accountant struct {
|
|
||||||
Accounts map[string]Account `json:"accounts"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAccountant creates a new accountant
|
|
||||||
func NewAccountant() *Accountant {
|
|
||||||
return &Accountant{
|
|
||||||
Accounts: make(map[string]Account),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterAccount adds an account to the set of internal accounts
|
|
||||||
func (a *Accountant) RegisterAccount(name string) (acc Account, err error) {
|
|
||||||
|
|
||||||
// Set up the account info
|
|
||||||
acc.Name = name
|
|
||||||
acc.Data = make(map[string]string)
|
|
||||||
|
|
||||||
// Verify this acount isn't already registered
|
|
||||||
for _, a := range a.Accounts {
|
|
||||||
if a.Name == acc.Name {
|
|
||||||
return Account{}, fmt.Errorf("account name already registered: %s", a.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the creation time
|
|
||||||
acc.Data["created"] = time.Now().String()
|
|
||||||
|
|
||||||
// Create a secret
|
|
||||||
acc.Data["secret"] = uuid.New().String()
|
|
||||||
|
|
||||||
// Simply add the account to the map
|
|
||||||
a.Accounts[acc.Name] = acc
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySecret verifies if an account secret is correct
|
|
||||||
func (a *Accountant) VerifySecret(account string, secret string) (bool, error) {
|
|
||||||
// Find the account matching the ID
|
|
||||||
if this, ok := a.Accounts[account]; ok {
|
|
||||||
return this.Data["secret"] == secret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, fmt.Errorf("no account found for id: %s", account)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssignData assigns data to an account
|
|
||||||
func (a *Accountant) AssignData(account string, key string, value string) error {
|
|
||||||
|
|
||||||
// Find the account matching the ID
|
|
||||||
if this, ok := a.Accounts[account]; ok {
|
|
||||||
this.Data[key] = value
|
|
||||||
a.Accounts[account] = this
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("no account found for id: %s", account)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetValue gets the rover rover for the account
|
|
||||||
func (a *Accountant) GetValue(account string, key string) (string, error) {
|
|
||||||
// Find the account matching the ID
|
|
||||||
this, ok := a.Accounts[account]
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("no account found for id: %s", account)
|
|
||||||
}
|
|
||||||
return this.Data[key], nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
func TestNewAccountant(t *testing.T) {
|
func TestNewAccountant(t *testing.T) {
|
||||||
// Very basic verify here for now
|
// Very basic verify here for now
|
||||||
accountant := NewAccountant()
|
accountant := NewSimpleAccountant()
|
||||||
if accountant == nil {
|
if accountant == nil {
|
||||||
t.Error("Failed to create accountant")
|
t.Error("Failed to create accountant")
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ func TestNewAccountant(t *testing.T) {
|
||||||
|
|
||||||
func TestAccountant_RegisterAccount(t *testing.T) {
|
func TestAccountant_RegisterAccount(t *testing.T) {
|
||||||
|
|
||||||
accountant := NewAccountant()
|
accountant := NewSimpleAccountant()
|
||||||
|
|
||||||
// Start by making two accounts
|
// Start by making two accounts
|
||||||
|
|
||||||
|
@ -44,10 +44,7 @@ func TestAccountant_RegisterAccount(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccountant_AssignGetData(t *testing.T) {
|
func TestAccountant_AssignGetData(t *testing.T) {
|
||||||
accountant := NewAccountant()
|
accountant := NewSimpleAccountant()
|
||||||
if len(accountant.Accounts) != 0 {
|
|
||||||
t.Error("New accountant created with non-zero account number")
|
|
||||||
}
|
|
||||||
|
|
||||||
name := uuid.New().String()
|
name := uuid.New().String()
|
||||||
a, err := accountant.RegisterAccount(name)
|
a, err := accountant.RegisterAccount(name)
|
||||||
|
|
90
pkg/accounts/simpleAccountant.go
Normal file
90
pkg/accounts/simpleAccountant.go
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package accounts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SimpleAccountant manages a set of accounts
|
||||||
|
type SimpleAccountant struct {
|
||||||
|
Accounts map[string]Account `json:"accounts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSimpleAccountant creates a new accountant
|
||||||
|
func NewSimpleAccountant() Accountant {
|
||||||
|
return &SimpleAccountant{
|
||||||
|
Accounts: make(map[string]Account),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterAccount adds an account to the set of internal accounts
|
||||||
|
func (a *SimpleAccountant) RegisterAccount(name string) (acc Account, err error) {
|
||||||
|
|
||||||
|
// Set up the account info
|
||||||
|
acc.Name = name
|
||||||
|
acc.Data = make(map[string]string)
|
||||||
|
|
||||||
|
// Verify this acount isn't already registered
|
||||||
|
for _, a := range a.Accounts {
|
||||||
|
if a.Name == acc.Name {
|
||||||
|
return Account{}, fmt.Errorf("account name already registered: %s", a.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the creation time
|
||||||
|
acc.Data["created"] = time.Now().String()
|
||||||
|
|
||||||
|
// Create a secret
|
||||||
|
acc.Data["secret"] = uuid.New().String()
|
||||||
|
|
||||||
|
// Simply add the account to the map
|
||||||
|
a.Accounts[acc.Name] = acc
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifySecret verifies if an account secret is correct
|
||||||
|
func (a *SimpleAccountant) VerifySecret(account string, secret string) (bool, error) {
|
||||||
|
// Find the account matching the ID
|
||||||
|
if this, ok := a.Accounts[account]; ok {
|
||||||
|
return this.Data["secret"] == secret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("no account found for id: %s", account)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSecret gets the internal secret
|
||||||
|
func (a *SimpleAccountant) GetSecret(account string) (string, error) {
|
||||||
|
// Find the account matching the ID
|
||||||
|
if this, ok := a.Accounts[account]; ok {
|
||||||
|
return this.Data["secret"], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("no account found for id: %s", account)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignData assigns data to an account
|
||||||
|
func (a *SimpleAccountant) AssignData(account string, key string, value string) error {
|
||||||
|
|
||||||
|
// Find the account matching the ID
|
||||||
|
if this, ok := a.Accounts[account]; ok {
|
||||||
|
this.Data[key] = value
|
||||||
|
a.Accounts[account] = this
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("no account found for id: %s", account)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetValue gets the rover rover for the account
|
||||||
|
func (a *SimpleAccountant) GetValue(account string, key string) (string, error) {
|
||||||
|
// Find the account matching the ID
|
||||||
|
this, ok := a.Accounts[account]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("no account found for id: %s", account)
|
||||||
|
}
|
||||||
|
return this.Data[key], nil
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue