initial commit
This commit is contained in:
commit
7e8842c630
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
9
.idea/loginToTemplate.iml
Normal file
9
.idea/loginToTemplate.iml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/loginToTemplate.iml" filepath="$PROJECT_DIR$/.idea/loginToTemplate.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
73
file_system_store.go
Normal file
73
file_system_store.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileSystemUserStore struct {
|
||||||
|
database *json.Encoder
|
||||||
|
userList UserList
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileSystemUserStore(file *os.File) (*FileSystemUserStore, error) {
|
||||||
|
err := initialiseUserDBFile(file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("problem initializing user db file, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userList, err := NewUserList(file)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("problem loading user list from file %s, %v", file.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FileSystemUserStore{
|
||||||
|
database: json.NewEncoder(&Tape{file}),
|
||||||
|
userList: userList,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initialiseUserDBFile(file *os.File) error {
|
||||||
|
file.Seek(0, 0)
|
||||||
|
|
||||||
|
info, err := file.Stat()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("problem getting file info from file %s, %v", file.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Size() == 0 {
|
||||||
|
file.Write([]byte("[]"))
|
||||||
|
file.Seek(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo add interface
|
||||||
|
|
||||||
|
func (f *FileSystemUserStore) AddUserToUserList(user User) {
|
||||||
|
f.userList = append(f.userList, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileSystemUserStore) DeleteUserFromUserList(user User) {
|
||||||
|
var userList []User
|
||||||
|
for _, u := range f.userList {
|
||||||
|
if !reflect.DeepEqual(u, user) {
|
||||||
|
userList = append(userList, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.userList = userList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileSystemUserStore) GetUsers() UserList {
|
||||||
|
return f.userList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileSystemUserStore) UpdateUserFromUserList(toUpdate, newState User) {
|
||||||
|
user := f.userList.Find(toUpdate.Username)
|
||||||
|
*user = newState
|
||||||
|
}
|
139
file_system_store_test.go
Normal file
139
file_system_store_test.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createTempFile(t testing.TB, initialDB string) (*os.File, func()) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
tempfile, err := ioutil.TempFile("", "db")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not create temp file %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tempfile.Write([]byte(initialDB))
|
||||||
|
|
||||||
|
removeFile := func() {
|
||||||
|
tempfile.Close()
|
||||||
|
os.Remove(tempfile.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempfile, removeFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileSystemStore(t *testing.T) {
|
||||||
|
t.Run("get username", func(t *testing.T) {
|
||||||
|
database, cleanDatabase := createTempFile(t, `[
|
||||||
|
{"Username": "testUser", "Key": "12345", "IpAddress": "123.123.123.123.50120", "IsAdmin": true},
|
||||||
|
{"Username": "jimmy", "Key": "67890", "IpAddress": "12.12.12.12:50121", "IsAdmin": false}]`)
|
||||||
|
defer cleanDatabase()
|
||||||
|
|
||||||
|
store, err := NewFileSystemUserStore(database)
|
||||||
|
|
||||||
|
//userList := store.userList
|
||||||
|
//user := userList.Find("testUser")
|
||||||
|
//user.UpdateAdminStatus(true)
|
||||||
|
|
||||||
|
AssertNoError(t, err)
|
||||||
|
|
||||||
|
got := store.GetUsers()
|
||||||
|
|
||||||
|
want := []User{
|
||||||
|
{Username: "testUser", Key: "12345", IpAddress: "123.123.123.123.50120", IsAdmin: true},
|
||||||
|
{Username: "jimmy", Key: "67890", IpAddress: "12.12.12.12:50121", IsAdmin: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertUsers(t, got, want)
|
||||||
|
|
||||||
|
//read again
|
||||||
|
got = store.GetUsers()
|
||||||
|
AssertUsers(t, got, want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateUser(t *testing.T) {
|
||||||
|
t.Run("get username", func(t *testing.T) {
|
||||||
|
database, cleanDatabase := createTempFile(t, `[
|
||||||
|
{"Username": "testUser", "Key": "12345", "IpAddress": "123.123.123.123.50120", "IsAdmin": true},
|
||||||
|
{"Username": "jimmy", "Key": "67890", "IpAddress": "12.12.12.12:50121", "IsAdmin": false}]`)
|
||||||
|
defer cleanDatabase()
|
||||||
|
|
||||||
|
store, err := NewFileSystemUserStore(database)
|
||||||
|
|
||||||
|
AssertNoError(t, err)
|
||||||
|
|
||||||
|
want := User{
|
||||||
|
Username: "newUser",
|
||||||
|
Key: "12345",
|
||||||
|
IpAddress: "1.1.1.1:1111",
|
||||||
|
IsAdmin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
store.AddUserToUserList(want)
|
||||||
|
|
||||||
|
got := store.GetUsers()
|
||||||
|
AssertUserExists(t, got, want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteUser(t *testing.T) {
|
||||||
|
t.Run("get username", func(t *testing.T) {
|
||||||
|
database, cleanDatabase := createTempFile(t, `[
|
||||||
|
{"Username": "testUser", "Key": "12345", "IpAddress": "123.123.123.123.50120", "IsAdmin": true},
|
||||||
|
{"Username": "jimmy", "Key": "67890", "IpAddress": "12.12.12.12:50121", "IsAdmin": false}]`)
|
||||||
|
defer cleanDatabase()
|
||||||
|
|
||||||
|
store, err := NewFileSystemUserStore(database)
|
||||||
|
|
||||||
|
AssertNoError(t, err)
|
||||||
|
|
||||||
|
want := User{
|
||||||
|
Username: "testUser",
|
||||||
|
Key: "12345",
|
||||||
|
IpAddress: "123.123.123.123:50120",
|
||||||
|
IsAdmin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
want = *store.userList.Find("testUser")
|
||||||
|
store.DeleteUserFromUserList(want)
|
||||||
|
|
||||||
|
got := store.GetUsers()
|
||||||
|
AssertUserNotExists(t, got, want)
|
||||||
|
|
||||||
|
want = *store.userList.Find("jimmy")
|
||||||
|
AssertUserExists(t, got, want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo move this to user_test.go and user.go
|
||||||
|
func TestUpdateUserStore(t *testing.T) {
|
||||||
|
t.Run("get username", func(t *testing.T) {
|
||||||
|
database, cleanDatabase := createTempFile(t, `[
|
||||||
|
{"Username": "testUser", "Key": "12345", "IpAddress": "123.123.123.123.50120", "IsAdmin": true},
|
||||||
|
{"Username": "jimmy", "Key": "67890", "IpAddress": "12.12.12.12:50121", "IsAdmin": false}]`)
|
||||||
|
defer cleanDatabase()
|
||||||
|
|
||||||
|
store, err := NewFileSystemUserStore(database)
|
||||||
|
|
||||||
|
AssertNoError(t, err)
|
||||||
|
|
||||||
|
userToUpdate := *store.userList.Find("testUser")
|
||||||
|
|
||||||
|
want := User{
|
||||||
|
Username: "testUser2",
|
||||||
|
Key: "123456",
|
||||||
|
IpAddress: "124.124.124.124:50120",
|
||||||
|
IsAdmin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
want = *store.userList.Find("testUser")
|
||||||
|
store.UpdateUserFromUserList(userToUpdate, want)
|
||||||
|
|
||||||
|
got := store.GetUsers()
|
||||||
|
AssertUserExists(t, got, want)
|
||||||
|
})
|
||||||
|
}
|
17
in_memory_user_store.go
Normal file
17
in_memory_user_store.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func NewInMemoryUserStore() *InMemoryUserStore {
|
||||||
|
return &InMemoryUserStore{map[string]string{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
type InMemoryUserStore struct {
|
||||||
|
store map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i InMemoryUserStore) GetUserName(name string) string {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i InMemoryUserStore) ShowIP(name string) string {
|
||||||
|
return i.store[name]
|
||||||
|
}
|
16
main.go
Normal file
16
main.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
const hostAndPort = ":5000"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
server := NewLoginServer(NewInMemoryUserStore())
|
||||||
|
|
||||||
|
if err := http.ListenAndServe(hostAndPort, server); err != nil {
|
||||||
|
log.Fatalf("could not listen on port %v", err)
|
||||||
|
}
|
||||||
|
}
|
57
server.go
Normal file
57
server.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserStore interface {
|
||||||
|
GetUserName(name string) string
|
||||||
|
ShowIP(name string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerHandler struct {
|
||||||
|
store UserStore
|
||||||
|
http.Handler
|
||||||
|
userIpMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLoginServer(store UserStore) *ServerHandler {
|
||||||
|
s := &ServerHandler{
|
||||||
|
store,
|
||||||
|
http.NewServeMux(),
|
||||||
|
nil,
|
||||||
|
}
|
||||||
|
router := http.NewServeMux()
|
||||||
|
router.Handle("/", http.HandlerFunc(s.homeHandler))
|
||||||
|
s.Handler = router
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerHandler) homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPost:
|
||||||
|
s.updateIpHandler(w, r)
|
||||||
|
case http.MethodGet:
|
||||||
|
s.sendHomeHandler(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerHandler) sendHomeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte(r.RemoteAddr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerHandler) updateIpHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
//userName := strings.TrimPrefix(r.URL.Path, "/")
|
||||||
|
//if ! s.store.GetUserName(userName)
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
w.Write([]byte(r.RemoteAddr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerHandler) GetUserName(name string) string {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerHandler) ShowIP(name string) string {
|
||||||
|
return s.userIpMap[name]
|
||||||
|
}
|
11
server_integration_test.go
Normal file
11
server_integration_test.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
//func TestPortalLoads(t *testing.T) {
|
||||||
|
// t.Run("Test Portal Loads", func(t *testing.T) {
|
||||||
|
// server := NewServer()
|
||||||
|
//
|
||||||
|
// servr.ServeHTTP(httptest.NewRecorder(), request)
|
||||||
|
//
|
||||||
|
// t.Run("")
|
||||||
|
// })
|
||||||
|
//}
|
48
server_test.go
Normal file
48
server_test.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const jsonContentType = "application/json"
|
||||||
|
|
||||||
|
func TestPortal(t *testing.T) {
|
||||||
|
store := StubUserStore{
|
||||||
|
map[string]string{
|
||||||
|
"testUser": "123.123.123.123:50120",
|
||||||
|
"jimmy": "12.12.12.12:50121",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
server := NewLoginServer(&store)
|
||||||
|
|
||||||
|
t.Run("Logs client ip", func(t *testing.T) {
|
||||||
|
for _, want := range store.userIpMap {
|
||||||
|
t.Run(fmt.Sprintf("got ip from "+want), func(t *testing.T) {
|
||||||
|
request := NewGetHomeRequest()
|
||||||
|
request.RemoteAddr = want
|
||||||
|
response := httptest.NewRecorder()
|
||||||
|
server.ServeHTTP(response, request)
|
||||||
|
got := response.Body.String()
|
||||||
|
|
||||||
|
AssertStatus(t, response.Code, http.StatusOK)
|
||||||
|
//todo we should update on post not get
|
||||||
|
AssertResponseBody(t, got, want)
|
||||||
|
//t.Fatalf("This test is bad, we should store on post not get")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Update client IP", func(t *testing.T) {
|
||||||
|
request := NewPutHomeRequest("testUser")
|
||||||
|
want := "5.5.5.5:10121"
|
||||||
|
request.RemoteAddr = want
|
||||||
|
response := httptest.NewRecorder()
|
||||||
|
server.ServeHTTP(response, request)
|
||||||
|
//todo make this fail
|
||||||
|
response.Body.String()
|
||||||
|
AssertStatus(t, response.Code, http.StatusAccepted)
|
||||||
|
})
|
||||||
|
}
|
14
tape.go
Normal file
14
tape.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// Tape represents an os.File that will re-write from the start on every Write call.
|
||||||
|
type Tape struct {
|
||||||
|
File *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tape) Write(p []byte) (n int, err error) {
|
||||||
|
t.File.Truncate(0)
|
||||||
|
t.File.Seek(0, 0)
|
||||||
|
return t.File.Write(p)
|
||||||
|
}
|
25
tape_test.go
Normal file
25
tape_test.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Tape_Write(t *testing.T) {
|
||||||
|
file, clean := createTempFile(t, "12345")
|
||||||
|
defer clean()
|
||||||
|
|
||||||
|
tape := Tape{File: file}
|
||||||
|
|
||||||
|
tape.Write([]byte("foo"))
|
||||||
|
|
||||||
|
file.Seek(0, 0)
|
||||||
|
contents, _ := ioutil.ReadAll(file)
|
||||||
|
|
||||||
|
got := string(contents)
|
||||||
|
want := "foo"
|
||||||
|
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("got %v want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
81
testing.go
Normal file
81
testing.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StubUserStore struct {
|
||||||
|
userIpMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StubUserStore) GetUserName(name string) string {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StubUserStore) ShowIP(name string) string {
|
||||||
|
return s.userIpMap[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertNoError(t testing.TB, err error) {
|
||||||
|
t.Helper()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("didn't expect an error, but got one, %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetHomeRequest() *http.Request {
|
||||||
|
req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("/"), nil)
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPutHomeRequest(userName string) *http.Request {
|
||||||
|
req, _ := http.NewRequest(http.MethodPost, fmt.Sprintf("/"+userName), nil)
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
func userInUserList(ul UserList, user User) bool {
|
||||||
|
for _, u := range ul {
|
||||||
|
if reflect.DeepEqual(u, user) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertResponseBody(t testing.TB, got, want string) {
|
||||||
|
t.Helper()
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("response body is wrong, got %q want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertStatus(t testing.TB, got, want int) {
|
||||||
|
t.Helper()
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("did not get correct status, expected %d got %d", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertUsers(t testing.TB, got, want []User) {
|
||||||
|
t.Helper()
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertUserExists(t testing.TB, got []User, want User) {
|
||||||
|
t.Helper()
|
||||||
|
if !userInUserList(got, want) {
|
||||||
|
t.Errorf("got %v want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertUserNotExists(t testing.TB, got []User, want User) {
|
||||||
|
t.Helper()
|
||||||
|
if userInUserList(got, want) {
|
||||||
|
t.Errorf("Expected %v to be deleted but it was not. List is %v", want, got)
|
||||||
|
}
|
||||||
|
}
|
20
user.go
Normal file
20
user.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Username string
|
||||||
|
Key string
|
||||||
|
IpAddress string
|
||||||
|
IsAdmin bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) UpdateUserKey(key string) {
|
||||||
|
u.Key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) UpdateUserIp(ipAddress string) {
|
||||||
|
u.IpAddress = ipAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) UpdateAdminStatus(isAdmin bool) {
|
||||||
|
u.IsAdmin = isAdmin
|
||||||
|
}
|
31
user_list.go
Normal file
31
user_list.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UserList stores a collection of users.
|
||||||
|
type UserList []User
|
||||||
|
|
||||||
|
// Find tries to return username from UserList
|
||||||
|
func (ul UserList) Find(username string) *User {
|
||||||
|
for i, u := range ul {
|
||||||
|
if u.Username == username {
|
||||||
|
return &ul[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUserList creates a UserList from JSON
|
||||||
|
func NewUserList(rdr io.Reader) (UserList, error) {
|
||||||
|
var userList []User
|
||||||
|
err := json.NewDecoder(rdr).Decode(&userList)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("problem parsing userlist, %v", err)
|
||||||
|
}
|
||||||
|
return userList, err
|
||||||
|
}
|
51
user_test.go
Normal file
51
user_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestUpdateUserKey(t *testing.T) {
|
||||||
|
user := User{
|
||||||
|
Username: "bob",
|
||||||
|
Key: "12345",
|
||||||
|
IpAddress: "12.12.12.12:50123",
|
||||||
|
IsAdmin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
want := "67890"
|
||||||
|
|
||||||
|
user.UpdateUserKey(want)
|
||||||
|
if user.Key != want {
|
||||||
|
t.Errorf("Expected key %v, got %v", want, user.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateUserIp(t *testing.T) {
|
||||||
|
user := User{
|
||||||
|
Username: "bob",
|
||||||
|
Key: "12345",
|
||||||
|
IpAddress: "12.12.12.12:50123",
|
||||||
|
IsAdmin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
want := "13.13.13.13:50124"
|
||||||
|
|
||||||
|
user.UpdateUserIp(want)
|
||||||
|
if user.IpAddress != want {
|
||||||
|
t.Errorf("Expected key %v, got %v", want, user.IpAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddAdmin(t *testing.T) {
|
||||||
|
user := User{
|
||||||
|
Username: "bob",
|
||||||
|
Key: "12345",
|
||||||
|
IpAddress: "12.12.12.12:50123",
|
||||||
|
IsAdmin: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
want := true
|
||||||
|
|
||||||
|
user.UpdateAdminStatus(want)
|
||||||
|
if user.IsAdmin != want {
|
||||||
|
t.Errorf("Expected key %v, got %v", want, user.IsAdmin)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user