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