@ -0,0 +1,140 @@ | |||||
package Auth_test | |||||
import ( | |||||
"bytes" | |||||
"encoding/base64" | |||||
"encoding/json" | |||||
"io/ioutil" | |||||
"log" | |||||
"net/http" | |||||
"net/http/httptest" | |||||
"testing" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||||
"github.com/gorilla/mux" | |||||
) | |||||
func Test_Login(t *testing.T) { | |||||
log.SetOutput(ioutil.Discard) | |||||
Database.InitTest() | |||||
r := mux.NewRouter() | |||||
Api.InitAPIEndpoints(r) | |||||
ts := httptest.NewServer(r) | |||||
defer ts.Close() | |||||
userKey, _ := Seeder.GenerateAesKey() | |||||
pubKey := Seeder.GetPubKey() | |||||
p, _ := Auth.HashPassword("password") | |||||
u := Models.User{ | |||||
Username: "test", | |||||
Password: p, | |||||
AsymmetricPublicKey: Seeder.PublicKey, | |||||
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey, | |||||
SymmetricKey: base64.StdEncoding.EncodeToString( | |||||
Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||||
), | |||||
} | |||||
err := Database.CreateUser(&u) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
d := struct { | |||||
Username string `json:"username"` | |||||
Password string `json:"password"` | |||||
}{ | |||||
Username: "test", | |||||
Password: "password", | |||||
} | |||||
jsonStr, _ := json.Marshal(d) | |||||
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/login", bytes.NewBuffer(jsonStr)) | |||||
req.Header.Set("Content-Type", "application/json") | |||||
client := &http.Client{} | |||||
resp, err := client.Do(req) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
if resp.StatusCode != http.StatusOK { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||||
return | |||||
} | |||||
var session Models.Session | |||||
err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error | |||||
if err != nil { | |||||
t.Errorf("Expected user record, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
} | |||||
func Test_Login_PasswordFails(t *testing.T) { | |||||
log.SetOutput(ioutil.Discard) | |||||
Database.InitTest() | |||||
r := mux.NewRouter() | |||||
Api.InitAPIEndpoints(r) | |||||
ts := httptest.NewServer(r) | |||||
defer ts.Close() | |||||
userKey, _ := Seeder.GenerateAesKey() | |||||
pubKey := Seeder.GetPubKey() | |||||
p, _ := Auth.HashPassword("password") | |||||
u := Models.User{ | |||||
Username: "test", | |||||
Password: p, | |||||
AsymmetricPublicKey: Seeder.PublicKey, | |||||
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey, | |||||
SymmetricKey: base64.StdEncoding.EncodeToString( | |||||
Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||||
), | |||||
} | |||||
err := Database.CreateUser(&u) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
d := struct { | |||||
Username string `json:"username"` | |||||
Password string `json:"password"` | |||||
}{ | |||||
Username: "test", | |||||
Password: "password1", | |||||
} | |||||
jsonStr, _ := json.Marshal(d) | |||||
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/login", bytes.NewBuffer(jsonStr)) | |||||
req.Header.Set("Content-Type", "application/json") | |||||
client := &http.Client{} | |||||
resp, err := client.Do(req) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
if resp.StatusCode != http.StatusUnauthorized { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusUnauthorized, resp.StatusCode) | |||||
return | |||||
} | |||||
} |
@ -0,0 +1,131 @@ | |||||
package Auth_test | |||||
import ( | |||||
"bytes" | |||||
"encoding/base64" | |||||
"encoding/json" | |||||
"io/ioutil" | |||||
"log" | |||||
"net/http" | |||||
"net/http/cookiejar" | |||||
"net/http/httptest" | |||||
"net/url" | |||||
"sync" | |||||
"testing" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||||
"github.com/gorilla/mux" | |||||
) | |||||
type Jar struct { | |||||
lk sync.Mutex | |||||
cookies map[string][]*http.Cookie | |||||
} | |||||
func Test_Logout(t *testing.T) { | |||||
log.SetOutput(ioutil.Discard) | |||||
Database.InitTest() | |||||
r := mux.NewRouter() | |||||
Api.InitAPIEndpoints(r) | |||||
ts := httptest.NewServer(r) | |||||
defer ts.Close() | |||||
userKey, _ := Seeder.GenerateAesKey() | |||||
pubKey := Seeder.GetPubKey() | |||||
p, _ := Auth.HashPassword("password") | |||||
u := Models.User{ | |||||
Username: "test", | |||||
Password: p, | |||||
AsymmetricPublicKey: Seeder.PublicKey, | |||||
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey, | |||||
SymmetricKey: base64.StdEncoding.EncodeToString( | |||||
Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||||
), | |||||
} | |||||
err := Database.CreateUser(&u) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
d := struct { | |||||
Username string `json:"username"` | |||||
Password string `json:"password"` | |||||
}{ | |||||
Username: "test", | |||||
Password: "password", | |||||
} | |||||
jsonStr, _ := json.Marshal(d) | |||||
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/login", bytes.NewBuffer(jsonStr)) | |||||
req.Header.Set("Content-Type", "application/json") | |||||
client := &http.Client{} | |||||
resp, err := client.Do(req) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
if resp.StatusCode != http.StatusOK { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||||
return | |||||
} | |||||
var session Models.Session | |||||
err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error | |||||
if err != nil { | |||||
t.Errorf("Expected session record, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
jar, err := cookiejar.New(nil) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
} | |||||
url, _ := url.Parse(ts.URL) | |||||
jar.SetCookies( | |||||
url, | |||||
[]*http.Cookie{ | |||||
&http.Cookie{ | |||||
Name: "session_token", | |||||
Value: session.ID.String(), | |||||
MaxAge: 300, | |||||
}, | |||||
}, | |||||
) | |||||
client = &http.Client{ | |||||
Jar: jar, | |||||
} | |||||
resp, err = client.Get(ts.URL + "/api/v1/logout") | |||||
if err != nil { | |||||
t.Errorf("Expected user record, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
if resp.StatusCode != http.StatusOK { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||||
return | |||||
} | |||||
err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error | |||||
if err == nil { | |||||
t.Errorf("Expected no session record, recieved %s", session.UserID) | |||||
return | |||||
} | |||||
} |
@ -0,0 +1,168 @@ | |||||
package Auth_test | |||||
import ( | |||||
"bytes" | |||||
"encoding/base64" | |||||
"encoding/json" | |||||
"io/ioutil" | |||||
"log" | |||||
"net/http" | |||||
"net/http/httptest" | |||||
"testing" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" | |||||
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||||
"github.com/gorilla/mux" | |||||
) | |||||
func Test_Signup(t *testing.T) { | |||||
log.SetOutput(ioutil.Discard) | |||||
Database.InitTest() | |||||
r := mux.NewRouter() | |||||
Api.InitAPIEndpoints(r) | |||||
ts := httptest.NewServer(r) | |||||
defer ts.Close() | |||||
userKey, _ := Seeder.GenerateAesKey() | |||||
pubKey := Seeder.GetPubKey() | |||||
d := struct { | |||||
Username string `json:"username"` | |||||
Password string `json:"password"` | |||||
ConfirmPassword string `json:"confirm_password"` | |||||
PubKey string `json:"asymmetric_public_key"` | |||||
PrivKey string `json:"asymmetric_private_key"` | |||||
SymKey string `json:"symmetric_key"` | |||||
}{ | |||||
Username: "test", | |||||
Password: "password", | |||||
ConfirmPassword: "password", | |||||
PubKey: Seeder.PublicKey, | |||||
PrivKey: Seeder.EncryptedPrivateKey, | |||||
SymKey: base64.StdEncoding.EncodeToString( | |||||
Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||||
), | |||||
} | |||||
jsonStr, _ := json.Marshal(d) | |||||
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/signup", bytes.NewBuffer(jsonStr)) | |||||
req.Header.Set("Content-Type", "application/json") | |||||
client := &http.Client{} | |||||
resp, err := client.Do(req) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
if resp.StatusCode != http.StatusNoContent { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode) | |||||
return | |||||
} | |||||
var user Models.User | |||||
err = Database.DB.First(&user, "username = ?", "test").Error | |||||
if err != nil { | |||||
t.Errorf("Expected user record, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
} | |||||
func Test_Signup_PasswordMismatchFails(t *testing.T) { | |||||
log.SetOutput(ioutil.Discard) | |||||
Database.InitTest() | |||||
r := mux.NewRouter() | |||||
Api.InitAPIEndpoints(r) | |||||
ts := httptest.NewServer(r) | |||||
defer ts.Close() | |||||
userKey, _ := Seeder.GenerateAesKey() | |||||
pubKey := Seeder.GetPubKey() | |||||
d := struct { | |||||
Username string `json:"username"` | |||||
Password string `json:"password"` | |||||
ConfirmPassword string `json:"confirm_password"` | |||||
PubKey string `json:"asymmetric_public_key"` | |||||
PrivKey string `json:"asymmetric_private_key"` | |||||
SymKey string `json:"symmetric_key"` | |||||
}{ | |||||
Username: "test", | |||||
Password: "password", | |||||
ConfirmPassword: "password1", | |||||
PubKey: Seeder.PublicKey, | |||||
PrivKey: Seeder.EncryptedPrivateKey, | |||||
SymKey: base64.StdEncoding.EncodeToString( | |||||
Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||||
), | |||||
} | |||||
jsonStr, _ := json.Marshal(d) | |||||
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/signup", bytes.NewBuffer(jsonStr)) | |||||
req.Header.Set("X-Custom-Header", "myvalue") | |||||
req.Header.Set("Content-Type", "application/json") | |||||
client := &http.Client{} | |||||
resp, err := client.Do(req) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
return | |||||
} | |||||
if resp.StatusCode != http.StatusUnprocessableEntity { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode) | |||||
return | |||||
} | |||||
} | |||||
func Test_Signup_MissingDataFails(t *testing.T) { | |||||
log.SetOutput(ioutil.Discard) | |||||
Database.InitTest() | |||||
r := mux.NewRouter() | |||||
Api.InitAPIEndpoints(r) | |||||
ts := httptest.NewServer(r) | |||||
defer ts.Close() | |||||
d := struct { | |||||
Username string `json:"username"` | |||||
Password string `json:"password"` | |||||
ConfirmPassword string `json:"confirm_password"` | |||||
PubKey string `json:"asymmetric_public_key"` | |||||
PrivKey string `json:"asymmetric_private_key"` | |||||
SymKey string `json:"symmetric_key"` | |||||
}{ | |||||
Username: "test", | |||||
Password: "password", | |||||
ConfirmPassword: "password", | |||||
PubKey: "", | |||||
PrivKey: "", | |||||
SymKey: "", | |||||
} | |||||
jsonStr, _ := json.Marshal(d) | |||||
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/signup", bytes.NewBuffer(jsonStr)) | |||||
req.Header.Set("X-Custom-Header", "myvalue") | |||||
req.Header.Set("Content-Type", "application/json") | |||||
client := &http.Client{} | |||||
resp, err := client.Do(req) | |||||
if err != nil { | |||||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||||
} | |||||
if resp.StatusCode != http.StatusUnprocessableEntity { | |||||
t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode) | |||||
} | |||||
} |
@ -0,0 +1,16 @@ | |||||
FROM golang:1.19-alpine | |||||
RUN mkdir -p /go/src/git.tovijaeschke.xyz/Capsule/Backend | |||||
COPY ./ /go/src/git.tovijaeschke.xyz/Capsule/Backend | |||||
WORKDIR /go/src/git.tovijaeschke.xyz/Capsule/Backend | |||||
# For "go test" | |||||
RUN apk add gcc libc-dev | |||||
RUN go mod download | |||||
RUN go build -o /go/bin/capsule-server main.go | |||||
CMD [ "/go/bin/capsule-server" ] |
@ -0,0 +1,49 @@ | |||||
version: "3" | |||||
services: | |||||
server: | |||||
build: | |||||
context: ./Backend | |||||
ports: | |||||
- "8080:8080" | |||||
volumes: | |||||
- "./Backend:/app" | |||||
links: | |||||
- postgres | |||||
- postgres-testing | |||||
depends_on: | |||||
postgres: | |||||
condition: service_healthy | |||||
depends_on: | |||||
postgres-testing: | |||||
condition: service_healthy | |||||
postgres: | |||||
image: postgres:14.5 | |||||
ports: | |||||
- "54321:5432" | |||||
environment: | |||||
POSTGRES_DB: capsule | |||||
POSTGRES_PASSWORD: password | |||||
volumes: | |||||
- /var/lib/postgres | |||||
healthcheck: | |||||
test: ["CMD-SHELL", "pg_isready -U postgres"] | |||||
interval: 5s | |||||
timeout: 5s | |||||
retries: 5 | |||||
postgres-testing: | |||||
image: postgres:14.5 | |||||
ports: | |||||
- "54322:5432" | |||||
environment: | |||||
POSTGRES_DB: capsule-testing | |||||
POSTGRES_PASSWORD: password | |||||
tmpfs: | |||||
- /var/lib/mysql | |||||
healthcheck: | |||||
test: ["CMD-SHELL", "pg_isready -U postgres"] | |||||
interval: 5s | |||||
timeout: 5s | |||||
retries: 5 | |||||
@ -0,0 +1,3 @@ | |||||
#!/bin/sh | |||||
docker-compose exec server sh -c "cd /app && go test -v ./Api/Auth" |