parent
62dbcd1135
commit
8bf90bea0b
@ -0,0 +1,9 @@
|
|||||||
|
ALLOWED_ORIGINS=*
|
||||||
|
DB_URL=http://localhost:8000
|
||||||
|
DB_TABLE=my-db-table
|
||||||
|
DB_GSI_NAME=gsi1
|
||||||
|
DB_GSI_ATTR=gsi1pk
|
||||||
|
AWS_ACCESS_KEY_ID=SecretAwsKey
|
||||||
|
AWS_SECRET_ACCESS_KEY=SecretAwsSecret
|
||||||
|
ENVIRONMENT=local-or-staging-or-production
|
||||||
|
LISTEN_ADDR=127.0.0.1:3000
|
||||||
@ -1,2 +1,4 @@
|
|||||||
.env*
|
.env*
|
||||||
!.env.local
|
!.env.example
|
||||||
|
dev/db/data/*
|
||||||
|
!dev/db/data/.keep
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
.PHONY: client
|
||||||
|
|
||||||
|
client:
|
||||||
|
@yarn --cwd ./client vite
|
||||||
|
|
||||||
|
api:
|
||||||
|
@echo 'Starting API Server...'
|
||||||
|
@go run ./main.go
|
||||||
|
|
||||||
|
test: test.api
|
||||||
|
|
||||||
|
test.api:
|
||||||
|
go test -v ./...
|
||||||
|
|
||||||
|
dynamo.start:
|
||||||
|
@cd ./dev/db && docker compose up -d
|
||||||
|
|
||||||
|
dynamo.stop:
|
||||||
|
@cd ./dev/db && docker compose down
|
||||||
|
|
||||||
|
dynamo.list:
|
||||||
|
@aws dynamodb list-tables --endpoint-url http://localhost:8000
|
||||||
|
|
||||||
|
dynamo.scan:
|
||||||
|
@aws dynamodb scan --table-name owltier-local --endpoint-url http://localhost:8000
|
||||||
|
|
||||||
|
dynamo.reset:
|
||||||
|
@cd ./dev/scripts && ./delete-table.sh
|
||||||
|
@sleep 1
|
||||||
|
@cd ./dev/scripts && ./create-table.sh
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
dynamodb-local:
|
||||||
|
command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
|
||||||
|
image: "amazon/dynamodb-local:latest"
|
||||||
|
container_name: dynamodb-local
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
volumes:
|
||||||
|
- "./data:/home/dynamodblocal/data"
|
||||||
|
working_dir: /home/dynamodblocal
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
aws dynamodb create-table --cli-input-json file://schema.json --endpoint-url http://localhost:8000 --output json
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
aws dynamodb delete-table --table-name 'owltier-local' --endpoint-url http://localhost:8000 --output json
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# In first time setup, the data folder that dynamo's docker image binds
|
||||||
|
# to had permissions set incorrectly so dynamo didnt work. This fixes that.
|
||||||
|
sudo chown $USER ./dev/db/data -R
|
||||||
|
chmod 775 -R ./dev/db/data
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"AttributeDefinitions": [
|
||||||
|
{
|
||||||
|
"AttributeName": "pk",
|
||||||
|
"AttributeType": "S"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AttributeName": "gsi1pk",
|
||||||
|
"AttributeType": "S"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TableName": "owltier-local",
|
||||||
|
"KeySchema": [
|
||||||
|
{
|
||||||
|
"AttributeName": "pk",
|
||||||
|
"KeyType": "HASH"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GlobalSecondaryIndexes": [
|
||||||
|
{
|
||||||
|
"IndexName": "gsi1",
|
||||||
|
"KeySchema": [
|
||||||
|
{
|
||||||
|
"AttributeName": "gsi1pk",
|
||||||
|
"KeyType": "HASH"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Projection": {
|
||||||
|
"ProjectionType": "ALL"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BillingMode": "PAY_PER_REQUEST",
|
||||||
|
"TableClass": "STANDARD"
|
||||||
|
}
|
||||||
@ -1,126 +0,0 @@
|
|||||||
package auth_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mnrva-dev/owltier.com/server/auth"
|
|
||||||
"github.com/mnrva-dev/owltier.com/server/db"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO also write unit tests
|
|
||||||
|
|
||||||
type userdata struct {
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
testuser = &db.UserSchema{
|
|
||||||
Username: "test",
|
|
||||||
Password: "testpassword1234!!",
|
|
||||||
}
|
|
||||||
permatestuser = &db.UserSchema{
|
|
||||||
Username: "user",
|
|
||||||
Password: "password1234!!",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func runTestServer() *httptest.Server {
|
|
||||||
return httptest.NewServer(auth.BuildRouter())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
m.Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegister(t *testing.T) {
|
|
||||||
ts := runTestServer()
|
|
||||||
defer ts.Close()
|
|
||||||
data := url.Values{}
|
|
||||||
data.Set("username", testuser.Username)
|
|
||||||
data.Set("password", testuser.Password)
|
|
||||||
resp, err := http.PostForm(fmt.Sprintf("%s/register", ts.URL), data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Could not read body")
|
|
||||||
}
|
|
||||||
if resp.StatusCode/100 != 2 {
|
|
||||||
t.Errorf("Expected status in 200-299 range, got %d", resp.StatusCode)
|
|
||||||
fmt.Println(string(body))
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLogin(t *testing.T) {
|
|
||||||
ts := runTestServer()
|
|
||||||
defer ts.Close()
|
|
||||||
data := url.Values{}
|
|
||||||
data.Set("username", testuser.Username)
|
|
||||||
data.Set("password", testuser.Password)
|
|
||||||
resp, err := http.PostForm(fmt.Sprintf("%s/login", ts.URL), data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Could not read body")
|
|
||||||
}
|
|
||||||
if resp.StatusCode/100 != 2 {
|
|
||||||
t.Errorf("Expected status in 200-299 range, got %d", resp.StatusCode)
|
|
||||||
fmt.Println(string(body))
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteAccount(t *testing.T) {
|
|
||||||
ts := runTestServer()
|
|
||||||
defer ts.Close()
|
|
||||||
data := url.Values{}
|
|
||||||
data.Set("username", testuser.Username)
|
|
||||||
data.Set("password", testuser.Password)
|
|
||||||
resp, err := http.PostForm(fmt.Sprintf("%s/login", ts.URL), data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Could not read body")
|
|
||||||
}
|
|
||||||
if resp.StatusCode/100 != 2 {
|
|
||||||
t.Error("Failed to login")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
// TODO: Fix this so that it uses session token
|
|
||||||
AccessToken := strings.Split(string(body), "\n")[0]
|
|
||||||
data = url.Values{}
|
|
||||||
data.Set("password", testuser.Password)
|
|
||||||
req, err := http.NewRequest("POST", fmt.Sprintf("%s/delete", ts.URL), strings.NewReader(data.Encode()))
|
|
||||||
req.Header.Add("Authorization", "Bearer "+AccessToken)
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
resp, err = http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
body, err = ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Could not read body")
|
|
||||||
}
|
|
||||||
// fmt.Println(string(body))
|
|
||||||
if resp.StatusCode/100 != 2 {
|
|
||||||
t.Errorf("Expected status in 200-299 range, got %d", resp.StatusCode)
|
|
||||||
fmt.Println(string(body))
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +1,123 @@
|
|||||||
package auth_test
|
package auth_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mnrva-dev/owltier.com/server/auth"
|
||||||
|
"github.com/mnrva-dev/owltier.com/server/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO also write unit tests
|
||||||
|
|
||||||
|
type userdata struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
testuser = &db.UserSchema{
|
||||||
|
Username: "test",
|
||||||
|
Password: "testpassword1234!!",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func runTestServer() *httptest.Server {
|
||||||
|
return httptest.NewServer(auth.BuildRouter())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegister(t *testing.T) {
|
||||||
|
ts := runTestServer()
|
||||||
|
defer ts.Close()
|
||||||
|
data := url.Values{}
|
||||||
|
data.Set("username", testuser.Username)
|
||||||
|
data.Set("password", testuser.Password)
|
||||||
|
resp, err := http.PostForm(fmt.Sprintf("%s/register", ts.URL), data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not read body")
|
||||||
|
}
|
||||||
|
if resp.StatusCode/100 != 2 {
|
||||||
|
t.Errorf("Expected status in 200-299 range, got %d", resp.StatusCode)
|
||||||
|
fmt.Println(string(body))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogin(t *testing.T) {
|
||||||
|
ts := runTestServer()
|
||||||
|
defer ts.Close()
|
||||||
|
data := url.Values{}
|
||||||
|
data.Set("username", testuser.Username)
|
||||||
|
data.Set("password", testuser.Password)
|
||||||
|
resp, err := http.PostForm(fmt.Sprintf("%s/login", ts.URL), data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not read body")
|
||||||
|
}
|
||||||
|
if resp.StatusCode/100 != 2 {
|
||||||
|
t.Errorf("Expected status in 200-299 range, got %d", resp.StatusCode)
|
||||||
|
fmt.Println(string(body))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteAccount(t *testing.T) {
|
||||||
|
ts := runTestServer()
|
||||||
|
defer ts.Close()
|
||||||
|
data := url.Values{}
|
||||||
|
data.Set("username", testuser.Username)
|
||||||
|
data.Set("password", testuser.Password)
|
||||||
|
resp, err := http.PostForm(fmt.Sprintf("%s/login", ts.URL), data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not read body")
|
||||||
|
}
|
||||||
|
if resp.StatusCode/100 != 2 {
|
||||||
|
t.Error("Failed to login")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
// TODO: Fix this so that it uses session token
|
||||||
|
sessionC := resp.Cookies()[0]
|
||||||
|
data = url.Values{}
|
||||||
|
data.Set("password", testuser.Password)
|
||||||
|
req, err := http.NewRequest("POST", fmt.Sprintf("%s/delete", ts.URL), strings.NewReader(data.Encode()))
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.AddCookie(sessionC)
|
||||||
|
fmt.Println("* Got session token ", sessionC.Value)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
resp, err = http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
body, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not read body")
|
||||||
|
}
|
||||||
|
// fmt.Println(string(body))
|
||||||
|
if resp.StatusCode/100 != 2 {
|
||||||
|
t.Errorf("Expected status in 200-299 range, got %d", resp.StatusCode)
|
||||||
|
fmt.Println(string(body))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
package auth_test
|
||||||
|
|
||||||
|
// TODO: test form validation
|
||||||
Loading…
Reference in new issue