add user type
parent
ddfa9535ab
commit
86ebe6bb90
@ -0,0 +1,56 @@
|
||||
package dbi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
APIKey string `json:"api_key"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Password string `json:"password"`
|
||||
Status string `json:"status"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
func CreateUser(conn *sql.Conn, user *User) error {
|
||||
_, err := conn.ExecContext(context.Background(),
|
||||
`INSERT INTO users (APIKey, FirstName, LastName, Password, Status, Username)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
user.APIKey, user.FirstName, user.LastName, user.Password, user.Status, user.Username,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetUser(conn *sql.Conn, username string) (User, error) {
|
||||
row := conn.QueryRowContext(context.Background(),
|
||||
`SELECT APIKey, FirstName, LastName, Password, Status, Username
|
||||
FROM users WHERE Username = ?`,
|
||||
username,
|
||||
)
|
||||
var u User
|
||||
err := row.Scan(&u.APIKey, &u.FirstName, &u.LastName, &u.Password, &u.Status, &u.Username)
|
||||
if err == sql.ErrNoRows {
|
||||
return User{}, fmt.Errorf("user %q not found", username)
|
||||
}
|
||||
return u, err
|
||||
}
|
||||
|
||||
func UpdateUser(conn *sql.Conn, user *User) error {
|
||||
_, err := conn.ExecContext(context.Background(),
|
||||
`UPDATE users SET APIKey = ?, FirstName = ?, LastName = ?, Password = ?, Status = ?
|
||||
WHERE Username = ?`,
|
||||
user.APIKey, user.FirstName, user.LastName, user.Password, user.Status, user.Username,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteUser(conn *sql.Conn, username string) error {
|
||||
_, err := conn.ExecContext(context.Background(),
|
||||
`DELETE FROM users WHERE Username = ?`,
|
||||
username,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
package dbi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func testDB(t *testing.T) *sql.DB {
|
||||
t.Helper()
|
||||
db, err := sql.Open("sqlite", ":memory:")
|
||||
if err != nil {
|
||||
t.Fatalf("open in-memory db: %v", err)
|
||||
}
|
||||
if _, err := db.Exec(ActivityReportSchema); err != nil {
|
||||
t.Fatalf("apply schema: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
return db
|
||||
}
|
||||
|
||||
func testConn(t *testing.T, db *sql.DB) *sql.Conn {
|
||||
t.Helper()
|
||||
conn, err := db.Conn(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("get conn: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { conn.Close() })
|
||||
return conn
|
||||
}
|
||||
|
||||
func randString(n int) string {
|
||||
const letters = "abcdefghijklmnopqrstuvwxyz"
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func genUser() User {
|
||||
return User{
|
||||
APIKey: randString(16),
|
||||
FirstName: randString(8),
|
||||
LastName: randString(8),
|
||||
Password: randString(20),
|
||||
Status: "faculty",
|
||||
Username: randString(10),
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
conn := testConn(t, testDB(t))
|
||||
u := genUser()
|
||||
|
||||
if err := CreateUser(conn, &u); err != nil {
|
||||
t.Fatalf("CreateUser: %v", err)
|
||||
}
|
||||
|
||||
got, err := GetUser(conn, u.Username)
|
||||
if err != nil {
|
||||
t.Fatalf("GetUser after create: %v", err)
|
||||
}
|
||||
if got != u {
|
||||
t.Errorf("got %+v, want %+v", got, u)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUserDuplicateUsername(t *testing.T) {
|
||||
conn := testConn(t, testDB(t))
|
||||
u := genUser()
|
||||
|
||||
if err := CreateUser(conn, &u); err != nil {
|
||||
t.Fatalf("first CreateUser: %v", err)
|
||||
}
|
||||
if err := CreateUser(conn, &u); err == nil {
|
||||
t.Error("expected error on duplicate username, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUser(t *testing.T) {
|
||||
conn := testConn(t, testDB(t))
|
||||
u := genUser()
|
||||
|
||||
if err := CreateUser(conn, &u); err != nil {
|
||||
t.Fatalf("CreateUser: %v", err)
|
||||
}
|
||||
|
||||
got, err := GetUser(conn, u.Username)
|
||||
if err != nil {
|
||||
t.Fatalf("GetUser: %v", err)
|
||||
}
|
||||
if got != u {
|
||||
t.Errorf("got %+v, want %+v", got, u)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUserNotFound(t *testing.T) {
|
||||
conn := testConn(t, testDB(t))
|
||||
|
||||
_, err := GetUser(conn, randString(10))
|
||||
if err == nil {
|
||||
t.Error("expected error for missing user, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUser(t *testing.T) {
|
||||
conn := testConn(t, testDB(t))
|
||||
u := genUser()
|
||||
|
||||
if err := CreateUser(conn, &u); err != nil {
|
||||
t.Fatalf("CreateUser: %v", err)
|
||||
}
|
||||
|
||||
u.FirstName = randString(8)
|
||||
u.LastName = randString(8)
|
||||
u.APIKey = randString(16)
|
||||
u.Status = "admin"
|
||||
|
||||
if err := UpdateUser(conn, &u); err != nil {
|
||||
t.Fatalf("UpdateUser: %v", err)
|
||||
}
|
||||
|
||||
got, err := GetUser(conn, u.Username)
|
||||
if err != nil {
|
||||
t.Fatalf("GetUser after update: %v", err)
|
||||
}
|
||||
if got != u {
|
||||
t.Errorf("got %+v, want %+v", got, u)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteUser(t *testing.T) {
|
||||
conn := testConn(t, testDB(t))
|
||||
u := genUser()
|
||||
|
||||
if err := CreateUser(conn, &u); err != nil {
|
||||
t.Fatalf("CreateUser: %v", err)
|
||||
}
|
||||
|
||||
if err := DeleteUser(conn, u.Username); err != nil {
|
||||
t.Fatalf("DeleteUser: %v", err)
|
||||
}
|
||||
|
||||
_, err := GetUser(conn, u.Username)
|
||||
if err == nil {
|
||||
t.Error("expected error after delete, got nil")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue