| @ -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" | |||||