From 2a368acc44ff4ac878fb31452d599db80b453849 Mon Sep 17 00:00:00 2001 From: Tovi Jaeschke-Rogers Date: Tue, 13 Sep 2022 21:51:58 +0930 Subject: [PATCH] Update tests --- Backend/Api/Auth/AddProfileImage_test.go | 70 +---- Backend/Api/Auth/ChangeMessageExpiry_test.go | 133 +-------- Backend/Api/Auth/ChangePassword_test.go | 188 +------------ Backend/Api/Auth/Login_test.go | 63 +---- Backend/Api/Auth/Logout_test.go | 90 +------ Backend/Api/Friends/EncryptedFriendsList.go | 4 +- Backend/Api/Messages/Conversations.go | 19 +- Backend/Api/Messages/Conversations_test.go | 255 ++++++++++++++++++ Backend/Api/Messages/CreateConversation.go | 2 +- .../Api/Messages/CreateConversation_test.go | 129 +++++++++ Backend/Api/Messages/CreateMessage.go | 19 +- Backend/Api/Messages/CreateMessage_test.go | 131 +++++++++ Backend/Api/Routes.go | 6 +- Backend/Database/Init.go | 48 ++-- Backend/Database/Seeder/encryption.go | 5 + Backend/Database/UserConversations.go | 10 +- Backend/Models/Conversations.go | 3 + Backend/Models/Messages.go | 3 +- Backend/Tests/Init.go | 87 ++++++ Backend/go.mod | 1 - test.sh | 2 +- 21 files changed, 711 insertions(+), 557 deletions(-) create mode 100644 Backend/Api/Messages/Conversations_test.go create mode 100644 Backend/Api/Messages/CreateConversation_test.go create mode 100644 Backend/Api/Messages/CreateMessage_test.go create mode 100644 Backend/Tests/Init.go diff --git a/Backend/Api/Auth/AddProfileImage_test.go b/Backend/Api/Auth/AddProfileImage_test.go index eb0864f..c0d0dc3 100644 --- a/Backend/Api/Auth/AddProfileImage_test.go +++ b/Backend/Api/Auth/AddProfileImage_test.go @@ -4,84 +4,24 @@ import ( "bytes" "encoding/base64" "encoding/json" - "io/ioutil" - "log" "net/http" - "net/http/cookiejar" - "net/http/httptest" - "net/url" "os" "testing" - "time" - "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" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" ) func Test_AddProfileImage(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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 - } - - session := Models.Session{ - UserID: u.ID, - Expiry: time.Now().Add(12 * time.Hour), - } - - err = Database.CreateSession(&session) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return } - jar, err := cookiejar.New(nil) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - url, _ := url.Parse(ts.URL) - - jar.SetCookies( - url, - []*http.Cookie{ - { - Name: "session_token", - Value: session.ID.String(), - MaxAge: 300, - }, - }, - ) - key, err := Seeder.GenerateAesKey() if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) @@ -110,10 +50,6 @@ func Test_AddProfileImage(t *testing.T) { req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/image", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") - client := &http.Client{ - Jar: jar, - } - resp, err := client.Do(req) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) @@ -125,7 +61,7 @@ func Test_AddProfileImage(t *testing.T) { return } - u, err = Database.GetUserById(u.ID.String()) + u, err := Database.GetUserByUsername("test") if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return diff --git a/Backend/Api/Auth/ChangeMessageExpiry_test.go b/Backend/Api/Auth/ChangeMessageExpiry_test.go index 03012dc..2c48c75 100644 --- a/Backend/Api/Auth/ChangeMessageExpiry_test.go +++ b/Backend/Api/Auth/ChangeMessageExpiry_test.go @@ -2,85 +2,22 @@ package Auth_test import ( "bytes" - "encoding/base64" "encoding/json" - "io/ioutil" - "log" "net/http" - "net/http/cookiejar" - "net/http/httptest" - "net/url" "testing" - "time" - "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" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" ) func Test_ChangeMessageExpiry(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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 - } - - session := Models.Session{ - UserID: u.ID, - Expiry: time.Now().Add(12 * time.Hour), - } - - err = Database.CreateSession(&session) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return } - jar, err := cookiejar.New(nil) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - url, _ := url.Parse(ts.URL) - - jar.SetCookies( - url, - []*http.Cookie{ - { - Name: "session_token", - Value: session.ID.String(), - MaxAge: 300, - }, - }, - ) - d := struct { MessageExpiry string `json:"message_expiry"` }{ @@ -91,10 +28,6 @@ func Test_ChangeMessageExpiry(t *testing.T) { req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") - client := &http.Client{ - Jar: jar, - } - resp, err := client.Do(req) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) @@ -105,7 +38,7 @@ func Test_ChangeMessageExpiry(t *testing.T) { t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode) } - u, err = Database.GetUserById(u.ID.String()) + u, err := Database.GetUserByUsername("test") if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return @@ -117,65 +50,13 @@ func Test_ChangeMessageExpiry(t *testing.T) { } func Test_ChangeMessageExpiryInvalidData(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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 - } - - session := Models.Session{ - UserID: u.ID, - Expiry: time.Now().Add(12 * time.Hour), - } - - err = Database.CreateSession(&session) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return } - jar, err := cookiejar.New(nil) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - url, _ := url.Parse(ts.URL) - - jar.SetCookies( - url, - []*http.Cookie{ - { - Name: "session_token", - Value: session.ID.String(), - MaxAge: 300, - }, - }, - ) - d := struct { MessageExpiry string `json:"message_expiry"` }{ @@ -186,10 +67,6 @@ func Test_ChangeMessageExpiryInvalidData(t *testing.T) { req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") - client := &http.Client{ - Jar: jar, - } - resp, err := client.Do(req) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) @@ -200,7 +77,7 @@ func Test_ChangeMessageExpiryInvalidData(t *testing.T) { t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode) } - u, err = Database.GetUserById(u.ID.String()) + u, err := Database.GetUserByUsername("test") if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return diff --git a/Backend/Api/Auth/ChangePassword_test.go b/Backend/Api/Auth/ChangePassword_test.go index 53d9491..29c1e42 100644 --- a/Backend/Api/Auth/ChangePassword_test.go +++ b/Backend/Api/Auth/ChangePassword_test.go @@ -2,85 +2,23 @@ package Auth_test import ( "bytes" - "encoding/base64" "encoding/json" - "io/ioutil" - "log" "net/http" - "net/http/cookiejar" - "net/http/httptest" - "net/url" "testing" - "time" - "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" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" ) func Test_ChangePassword(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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 } - session := Models.Session{ - UserID: u.ID, - Expiry: time.Now().Add(12 * time.Hour), - } - - err = Database.CreateSession(&session) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - jar, err := cookiejar.New(nil) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - url, _ := url.Parse(ts.URL) - - jar.SetCookies( - url, - []*http.Cookie{ - { - Name: "session_token", - Value: session.ID.String(), - MaxAge: 300, - }, - }, - ) - d := struct { OldPassword string `json:"old_password"` NewPassword string `json:"new_password"` @@ -97,10 +35,6 @@ func Test_ChangePassword(t *testing.T) { req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") - client := &http.Client{ - Jar: jar, - } - resp, err := client.Do(req) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) @@ -112,7 +46,7 @@ func Test_ChangePassword(t *testing.T) { return } - u, err = Database.GetUserById(u.ID.String()) + u, err := Database.GetUserByUsername("test") if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return @@ -124,65 +58,13 @@ func Test_ChangePassword(t *testing.T) { } func Test_ChangePasswordMismatchConfirmFails(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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 - } - - session := Models.Session{ - UserID: u.ID, - Expiry: time.Now().Add(12 * time.Hour), - } - - err = Database.CreateSession(&session) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) return } - jar, err := cookiejar.New(nil) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - url, _ := url.Parse(ts.URL) - - jar.SetCookies( - url, - []*http.Cookie{ - { - Name: "session_token", - Value: session.ID.String(), - MaxAge: 300, - }, - }, - ) - d := struct { OldPassword string `json:"old_password"` NewPassword string `json:"new_password"` @@ -199,10 +81,6 @@ func Test_ChangePasswordMismatchConfirmFails(t *testing.T) { req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") - client := &http.Client{ - Jar: jar, - } - resp, err := client.Do(req) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) @@ -215,65 +93,13 @@ func Test_ChangePasswordMismatchConfirmFails(t *testing.T) { } func Test_ChangePasswordInvalidCurrentPasswordFails(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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 } - session := Models.Session{ - UserID: u.ID, - Expiry: time.Now().Add(12 * time.Hour), - } - - err = Database.CreateSession(&session) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - jar, err := cookiejar.New(nil) - if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) - return - } - - url, _ := url.Parse(ts.URL) - - jar.SetCookies( - url, - []*http.Cookie{ - { - Name: "session_token", - Value: session.ID.String(), - MaxAge: 300, - }, - }, - ) - d := struct { OldPassword string `json:"old_password"` NewPassword string `json:"new_password"` @@ -290,10 +116,6 @@ func Test_ChangePasswordInvalidCurrentPasswordFails(t *testing.T) { req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") - client := &http.Client{ - Jar: jar, - } - resp, err := client.Do(req) if err != nil { t.Errorf("Expected nil, recieved %s", err.Error()) diff --git a/Backend/Api/Auth/Login_test.go b/Backend/Api/Auth/Login_test.go index 11ea4af..7eef436 100644 --- a/Backend/Api/Auth/Login_test.go +++ b/Backend/Api/Auth/Login_test.go @@ -2,47 +2,18 @@ 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" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" ) func Test_Login(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + _, ts, err := Tests.InitTestEnv() 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 @@ -73,6 +44,12 @@ func Test_Login(t *testing.T) { return } + u, err := Database.GetUserByUsername("test") + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + var session Models.Session err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error @@ -84,30 +61,8 @@ func Test_Login(t *testing.T) { } func Test_Login_PasswordFails(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + _, ts, err := Tests.InitTestEnv() 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 diff --git a/Backend/Api/Auth/Logout_test.go b/Backend/Api/Auth/Logout_test.go index 85c2516..2903bb3 100644 --- a/Backend/Api/Auth/Logout_test.go +++ b/Backend/Api/Auth/Logout_test.go @@ -1,72 +1,26 @@ package Auth_test import ( - "bytes" - "encoding/base64" - "encoding/json" - "io/ioutil" - "log" "net/http" - "net/http/cookiejar" - "net/http/httptest" - "net/url" "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" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" ) func Test_Logout(t *testing.T) { - log.SetOutput(ioutil.Discard) - Database.InitTest() - - r := mux.NewRouter() - Api.InitAPIEndpoints(r) - ts := httptest.NewServer(r) + client, ts, err := Tests.InitTestEnv() 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) + resp, err := client.Get(ts.URL + "/api/v1/logout") if err != nil { - t.Errorf("Expected nil, recieved %s", err.Error()) + t.Errorf("Expected user record, recieved %s", err.Error()) return } @@ -77,46 +31,12 @@ func Test_Logout(t *testing.T) { 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") - + u, err := Database.GetUserByUsername("test") 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) diff --git a/Backend/Api/Friends/EncryptedFriendsList.go b/Backend/Api/Friends/EncryptedFriendsList.go index c2ea274..79d6113 100644 --- a/Backend/Api/Friends/EncryptedFriendsList.go +++ b/Backend/Api/Friends/EncryptedFriendsList.go @@ -9,8 +9,8 @@ import ( "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" ) -// EncryptedFriendRequestList gets friend request list -func EncryptedFriendRequestList(w http.ResponseWriter, r *http.Request) { +// FriendRequestList gets friend request list +func FriendRequestList(w http.ResponseWriter, r *http.Request) { var ( userSession Models.Session friends []Models.FriendRequest diff --git a/Backend/Api/Messages/Conversations.go b/Backend/Api/Messages/Conversations.go index 4678108..e4c6e81 100644 --- a/Backend/Api/Messages/Conversations.go +++ b/Backend/Api/Messages/Conversations.go @@ -4,6 +4,7 @@ import ( "encoding/json" "net/http" "net/url" + "strconv" "strings" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth" @@ -11,15 +12,24 @@ import ( "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" ) -// EncryptedConversationList returns an encrypted list of all Conversations -func EncryptedConversationList(w http.ResponseWriter, r *http.Request) { +// ConversationList returns an encrypted list of all Conversations +func ConversationList(w http.ResponseWriter, r *http.Request) { var ( conversationDetails []Models.UserConversation userSession Models.Session returnJSON []byte + values url.Values + page int err error ) + values = r.URL.Query() + + page, err = strconv.Atoi(values.Get("page")) + if err != nil { + page = 0 + } + userSession, err = Auth.CheckCookie(r) if err != nil { http.Error(w, "Forbidden", http.StatusUnauthorized) @@ -28,6 +38,7 @@ func EncryptedConversationList(w http.ResponseWriter, r *http.Request) { conversationDetails, err = Database.GetUserConversationsByUserId( userSession.UserID.String(), + page, ) if err != nil { http.Error(w, "Error", http.StatusInternalServerError) @@ -44,8 +55,8 @@ func EncryptedConversationList(w http.ResponseWriter, r *http.Request) { w.Write(returnJSON) } -// EncryptedConversationDetailsList returns an encrypted list of all ConversationDetails -func EncryptedConversationDetailsList(w http.ResponseWriter, r *http.Request) { +// ConversationDetailsList returns an encrypted list of all ConversationDetails +func ConversationDetailsList(w http.ResponseWriter, r *http.Request) { var ( conversationDetails []Models.ConversationDetail detail Models.ConversationDetail diff --git a/Backend/Api/Messages/Conversations_test.go b/Backend/Api/Messages/Conversations_test.go new file mode 100644 index 0000000..21163ce --- /dev/null +++ b/Backend/Api/Messages/Conversations_test.go @@ -0,0 +1,255 @@ +package Messages_test + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "testing" + + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" +) + +func Test_ConversationsList(t *testing.T) { + client, ts, err := Tests.InitTestEnv() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + u, err := Database.GetUserByUsername("test") + + key, err := Seeder.GenerateAesKey() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + nameCiphertext, err := key.AesEncrypt([]byte("Test conversation")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + twoUserCiphertext, err := key.AesEncrypt([]byte("false")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + messageThread := Models.ConversationDetail{ + Name: base64.StdEncoding.EncodeToString(nameCiphertext), + TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext), + } + + err = Database.CreateConversationDetail(&messageThread) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(messageThread.ID.String())) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + adminCiphertext, err := key.AesEncrypt([]byte("true")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + pubKey := Seeder.GetPubKey() + + messageThreadUser := Models.UserConversation{ + UserID: u.ID, + ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext), + Admin: base64.StdEncoding.EncodeToString(adminCiphertext), + SymmetricKey: base64.StdEncoding.EncodeToString( + Seeder.EncryptWithPublicKey(key.Key, pubKey), + ), + } + + err = Database.CreateUserConversation(&messageThreadUser) + + req, _ := http.NewRequest("GET", ts.URL+"/api/v1/auth/conversations", nil) + + 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 + } + + requestBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + + var conversations []Models.UserConversation + + json.Unmarshal(requestBody, &conversations) + + if len(conversations) != 1 { + t.Errorf("Expected %d, recieved %d", 1, len(conversations)) + } + + conv := conversations[0] + + decodedId, err := base64.StdEncoding.DecodeString(conv.ConversationDetailID) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + decrypedId, err := key.AesDecrypt(decodedId) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + + req, _ = http.NewRequest( + "GET", + ts.URL+"/api/v1/auth/conversation_details?conversation_detail_ids="+string(decrypedId), + nil, + ) + + resp, err = client.Do(req) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + var conversationDetails []Models.ConversationDetail + + requestBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + + json.Unmarshal(requestBody, &conversationDetails) + + if len(conversationDetails) != 1 { + t.Errorf("Expected %d, recieved %d", 1, len(conversations)) + } + + decodedName, err := base64.StdEncoding.DecodeString(conversationDetails[0].Name) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + decrypedName, err := key.AesDecrypt(decodedName) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + + if string(decrypedName) != "Test conversation" { + t.Errorf("Expected %s, recieved %s", "Test converation", string(decrypedName)) + } +} + +func Test_ConversationsListPagination(t *testing.T) { + client, ts, err := Tests.InitTestEnv() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + u, err := Database.GetUserByUsername("test") + + key, err := Seeder.GenerateAesKey() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + for i := 0; i < 40; i++ { + nameCiphertext, err := key.AesEncrypt([]byte( + fmt.Sprintf("Test conversation %d", i), + )) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + twoUserCiphertext, err := key.AesEncrypt([]byte("false")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + messageThread := Models.ConversationDetail{ + Name: base64.StdEncoding.EncodeToString(nameCiphertext), + TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext), + } + + err = Database.CreateConversationDetail(&messageThread) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(messageThread.ID.String())) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + adminCiphertext, err := key.AesEncrypt([]byte("true")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + pubKey := Seeder.GetPubKey() + + messageThreadUser := Models.UserConversation{ + UserID: u.ID, + ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext), + Admin: base64.StdEncoding.EncodeToString(adminCiphertext), + SymmetricKey: base64.StdEncoding.EncodeToString( + Seeder.EncryptWithPublicKey(key.Key, pubKey), + ), + } + + err = Database.CreateUserConversation(&messageThreadUser) + } + + req, _ := http.NewRequest("GET", ts.URL+"/api/v1/auth/conversations?page=0", nil) + + 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 + } + + requestBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) + return + } + + var conversations []Models.UserConversation + + json.Unmarshal(requestBody, &conversations) + + if len(conversations) != 20 { + t.Errorf("Expected %d, recieved %d", 1, len(conversations)) + } +} diff --git a/Backend/Api/Messages/CreateConversation.go b/Backend/Api/Messages/CreateConversation.go index 728ecb0..12d54e1 100644 --- a/Backend/Api/Messages/CreateConversation.go +++ b/Backend/Api/Messages/CreateConversation.go @@ -54,5 +54,5 @@ func CreateConversation(w http.ResponseWriter, r *http.Request) { return } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusNoContent) } diff --git a/Backend/Api/Messages/CreateConversation_test.go b/Backend/Api/Messages/CreateConversation_test.go new file mode 100644 index 0000000..7c0ee80 --- /dev/null +++ b/Backend/Api/Messages/CreateConversation_test.go @@ -0,0 +1,129 @@ +package Messages_test + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "net/http" + "testing" + + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" + "github.com/gofrs/uuid" +) + +func Test_CreateConversation(t *testing.T) { + client, ts, err := Tests.InitTestEnv() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + u, err := Database.GetUserByUsername("test") + + key, err := Seeder.GenerateAesKey() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + nameCiphertext, err := key.AesEncrypt([]byte("Test conversation")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + twoUserCiphertext, err := key.AesEncrypt([]byte("false")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + id, err := uuid.NewV4() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(id.String())) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + adminCiphertext, err := key.AesEncrypt([]byte("true")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + userIDCiphertext, err := key.AesEncrypt([]byte(u.ID.String())) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + usernameCiphertext, err := key.AesEncrypt([]byte(u.Username)) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + pubKey := Seeder.GetPubKey() + + d := struct { + ID string `json:"id"` + Name string `json:"name"` + TwoUser string `json:"two_user"` + Users []Models.ConversationDetailUser `json:"users"` + UserConversations []Models.UserConversation `json:"user_conversations"` + }{ + ID: id.String(), + Name: base64.StdEncoding.EncodeToString(nameCiphertext), + TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext), + Users: []Models.ConversationDetailUser{ + { + ConversationDetailID: id, + UserID: base64.StdEncoding.EncodeToString(userIDCiphertext), + Username: base64.StdEncoding.EncodeToString(usernameCiphertext), + AssociationKey: "", + PublicKey: "", + Admin: base64.StdEncoding.EncodeToString(adminCiphertext), + }, + }, + UserConversations: []Models.UserConversation{ + { + UserID: u.ID, + ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext), + Admin: base64.StdEncoding.EncodeToString(adminCiphertext), + SymmetricKey: base64.StdEncoding.EncodeToString( + Seeder.EncryptWithPublicKey(key.Key, pubKey), + ), + }, + }, + } + + jsonStr, _ := json.Marshal(d) + req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/conversations", bytes.NewBuffer(jsonStr)) + req.Header.Set("Content-Type", "application/json") + + 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) + } + + var c Models.ConversationDetail + err = Database.DB.First(&c, "id = ?", id.String()).Error + + if err != nil { + t.Errorf("Expected conversation detail record, received %s", err.Error()) + return + } +} diff --git a/Backend/Api/Messages/CreateMessage.go b/Backend/Api/Messages/CreateMessage.go index becc0c2..04cb15e 100644 --- a/Backend/Api/Messages/CreateMessage.go +++ b/Backend/Api/Messages/CreateMessage.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/json" "net/http" + "time" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" @@ -20,8 +21,11 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) { var ( messagesData []rawMessageData messageData rawMessageData + message Models.Message + t time.Time decodedFile []byte fileName string + i int err error ) @@ -38,6 +42,19 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) { messageData.MessageData.Attachment.FilePath = fileName } + for i, message = range messageData.Messages { + t, err = time.Parse("2006-01-02T15:04:05Z", message.ExpiryRaw) + if err != nil { + http.Error(w, "Error", http.StatusInternalServerError) + return + } + err = messageData.Messages[i].Expiry.Scan(t) + if err != nil { + http.Error(w, "Error", http.StatusInternalServerError) + return + } + } + err = Database.CreateMessageData(&messageData.MessageData) if err != nil { http.Error(w, "Error", http.StatusInternalServerError) @@ -51,5 +68,5 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) { } } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusNoContent) } diff --git a/Backend/Api/Messages/CreateMessage_test.go b/Backend/Api/Messages/CreateMessage_test.go new file mode 100644 index 0000000..35cfc51 --- /dev/null +++ b/Backend/Api/Messages/CreateMessage_test.go @@ -0,0 +1,131 @@ +package Messages_test + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "net/http" + "testing" + "time" + + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" + "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" + "github.com/gofrs/uuid" +) + +func Test_CreateMessage(t *testing.T) { + client, ts, err := Tests.InitTestEnv() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + u, err := Database.GetUserByUsername("test") + + key, err := Seeder.GenerateAesKey() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + dataCiphertext, err := key.AesEncrypt([]byte("Test message...")) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + senderIDCiphertext, err := key.AesEncrypt([]byte(u.ID.String())) + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + id, err := uuid.NewV4() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + id2, err := uuid.NewV4() + if err != nil { + t.Errorf("Expected nil, recieved %s", err.Error()) + return + } + + d := []struct { + MessageData struct { + ID uuid.UUID `json:"id"` + Data string `json:"data"` + SenderID string `json:"sender_id"` + SymmetricKey string `json:"symmetric_key"` + } `json:"message_data"` + Messages []struct { + ID uuid.UUID `json:"id"` + MessageDataID uuid.UUID `json:"message_data_id"` + SymmetricKey string `json:"symmetric_key"` + AssociationKey string `json:"association_key"` + Expiry time.Time `json:"expiry"` + } `json:"message"` + }{ + { + MessageData: struct { + ID uuid.UUID `json:"id"` + Data string `json:"data"` + SenderID string `json:"sender_id"` + SymmetricKey string `json:"symmetric_key"` + }{ + ID: id, + Data: base64.StdEncoding.EncodeToString(dataCiphertext), + SenderID: base64.StdEncoding.EncodeToString(senderIDCiphertext), + SymmetricKey: "", + }, + Messages: []struct { + ID uuid.UUID `json:"id"` + MessageDataID uuid.UUID `json:"message_data_id"` + SymmetricKey string `json:"symmetric_key"` + AssociationKey string `json:"association_key"` + Expiry time.Time `json:"expiry"` + }{ + { + ID: id2, + MessageDataID: id, + SymmetricKey: "", + AssociationKey: "", + Expiry: time.Now(), + }, + }, + }, + } + + jsonStr, _ := json.Marshal(d) + req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message", bytes.NewBuffer(jsonStr)) + req.Header.Set("Content-Type", "application/json") + + 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 m Models.Message + err = Database.DB.First(&m).Error + if err != nil { + t.Errorf("Expected conversation detail record, received %s", err.Error()) + return + } + + var md Models.MessageData + err = Database.DB.First(&md).Error + if err != nil { + t.Errorf("Expected conversation detail record, received %s", err.Error()) + return + } + +} diff --git a/Backend/Api/Routes.go b/Backend/Api/Routes.go index 4058644..73d98f4 100644 --- a/Backend/Api/Routes.go +++ b/Backend/Api/Routes.go @@ -68,14 +68,14 @@ func InitAPIEndpoints(router *mux.Router) { authAPI.HandleFunc("/users", Users.SearchUsers).Methods("GET") - authAPI.HandleFunc("/friend_requests", Friends.EncryptedFriendRequestList).Methods("GET") + authAPI.HandleFunc("/friend_requests", Friends.FriendRequestList).Methods("GET") authAPI.HandleFunc("/friend_request", Friends.CreateFriendRequest).Methods("POST") authAPI.HandleFunc("/friend_request/qr_code", Friends.CreateFriendRequestQrCode).Methods("POST") authAPI.HandleFunc("/friend_request/{requestID}", Friends.AcceptFriendRequest).Methods("POST") authAPI.HandleFunc("/friend_request/{requestID}", Friends.RejectFriendRequest).Methods("DELETE") - authAPI.HandleFunc("/conversations", Messages.EncryptedConversationList).Methods("GET") - authAPI.HandleFunc("/conversation_details", Messages.EncryptedConversationDetailsList).Methods("GET") + authAPI.HandleFunc("/conversations", Messages.ConversationList).Methods("GET") + authAPI.HandleFunc("/conversation_details", Messages.ConversationDetailsList).Methods("GET") authAPI.HandleFunc("/conversations", Messages.CreateConversation).Methods("POST") authAPI.HandleFunc("/conversations", Messages.UpdateConversation).Methods("PUT") authAPI.HandleFunc("/conversations/{detailID}/image", Messages.AddConversationImage).Methods("POST") diff --git a/Backend/Database/Init.go b/Backend/Database/Init.go index 0d1a729..982a7d4 100644 --- a/Backend/Database/Init.go +++ b/Backend/Database/Init.go @@ -12,30 +12,29 @@ import ( const ( dbURL = "postgres://postgres:password@postgres:5432/capsule" dbTestURL = "postgres://postgres:password@postgres-testing:5432/capsule-testing" + + PageSize = 20 ) // DB db var DB *gorm.DB -func getModels() []interface{} { - return []interface{}{ - &Models.Session{}, - &Models.Attachment{}, - &Models.User{}, - &Models.FriendRequest{}, - &Models.MessageData{}, - &Models.Message{}, - &Models.ConversationDetail{}, - &Models.ConversationDetailUser{}, - &Models.UserConversation{}, - } +var models = []interface{}{ + &Models.Session{}, + &Models.Attachment{}, + &Models.User{}, + &Models.FriendRequest{}, + &Models.MessageData{}, + &Models.Message{}, + &Models.ConversationDetail{}, + &Models.ConversationDetailUser{}, + &Models.UserConversation{}, } // Init initializes the database connection func Init() { var ( - model interface{} - err error + err error ) log.Println("Initializing database...") @@ -48,19 +47,16 @@ func Init() { log.Println("Running AutoMigrate...") - for _, model = range getModels() { - err = DB.AutoMigrate(model) - if err != nil { - log.Fatalln(err) - } + err = DB.AutoMigrate(models...) + if err != nil { + log.Fatalln(err) } } // InitTest initializes the test datbase func InitTest() { var ( - model interface{} - err error + err error ) DB, err = gorm.Open(postgres.Open(dbTestURL), &gorm.Config{}) @@ -69,8 +65,12 @@ func InitTest() { log.Fatalln(err) } - for _, model = range getModels() { - DB.Migrator().DropTable(model) - DB.AutoMigrate(model) + err = DB.Migrator().DropTable(models...) + if err != nil { + panic(err) + } + err = DB.AutoMigrate(models...) + if err != nil { + panic(err) } } diff --git a/Backend/Database/Seeder/encryption.go b/Backend/Database/Seeder/encryption.go index e0f5c74..101e5a4 100644 --- a/Backend/Database/Seeder/encryption.go +++ b/Backend/Database/Seeder/encryption.go @@ -153,6 +153,11 @@ func (key aesKey) AesDecrypt(ciphertext []byte) ([]byte, error) { decMode := cipher.NewCBCDecrypter(block, iv) decMode.CryptBlocks(plaintext, plaintext) + plaintext, err = pkcs7strip(plaintext, 16) + if err != nil { + return []byte{}, err + } + return plaintext, nil } diff --git a/Backend/Database/UserConversations.go b/Backend/Database/UserConversations.go index 2e77ce7..cc876c7 100644 --- a/Backend/Database/UserConversations.go +++ b/Backend/Database/UserConversations.go @@ -19,13 +19,19 @@ func GetUserConversationById(id string) (Models.UserConversation, error) { return message, err } -func GetUserConversationsByUserId(id string) ([]Models.UserConversation, error) { +func GetUserConversationsByUserId(id string, page int) ([]Models.UserConversation, error) { var ( conversations []Models.UserConversation + offset int err error ) - err = DB.Find(&conversations, "user_id = ?", id). + offset = page * PageSize + + err = DB.Offset(offset). + Limit(PageSize). + Order("created_at DESC"). + Find(&conversations, "user_id = ?", id). Error return conversations, err diff --git a/Backend/Models/Conversations.go b/Backend/Models/Conversations.go index 1c9e53a..6df37ec 100644 --- a/Backend/Models/Conversations.go +++ b/Backend/Models/Conversations.go @@ -1,6 +1,8 @@ package Models import ( + "time" + "github.com/gofrs/uuid" ) @@ -34,4 +36,5 @@ type UserConversation struct { ConversationDetailID string `gorm:"not null" json:"conversation_detail_id"` // Stored encrypted Admin string `gorm:"not null" json:"admin"` // Bool if user is admin of thread, stored encrypted SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted + CreatedAt time.Time `gorm:"not null" json:"created_at"` } diff --git a/Backend/Models/Messages.go b/Backend/Models/Messages.go index bf05e3b..eafac22 100644 --- a/Backend/Models/Messages.go +++ b/Backend/Models/Messages.go @@ -25,6 +25,7 @@ type Message struct { MessageData MessageData ` json:"message_data"` SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted AssociationKey string `gorm:"not null" json:"association_key"` // Stored encrypted - Expiry sql.NullTime ` json:"expiry"` + ExpiryRaw string ` json:"expiry"` + Expiry sql.NullTime ` json:"-"` CreatedAt time.Time `gorm:"not null" json:"created_at"` } diff --git a/Backend/Tests/Init.go b/Backend/Tests/Init.go new file mode 100644 index 0000000..fdb4b48 --- /dev/null +++ b/Backend/Tests/Init.go @@ -0,0 +1,87 @@ +package Tests + +import ( + "encoding/base64" + "io/ioutil" + "log" + "net/http" + "net/http/cookiejar" + "net/http/httptest" + "net/url" + "time" + + "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" +) + +// InitTestEnv initializes the test environment +// client is used for making authenticated requests +// ts is the testing server +// err, in case it fails ¯\_(ツ)_/¯ +func InitTestEnv() (*http.Client, *httptest.Server, error) { + log.SetOutput(ioutil.Discard) + Database.InitTest() + + r := mux.NewRouter() + Api.InitAPIEndpoints(r) + ts := httptest.NewServer(r) + + userKey, err := Seeder.GenerateAesKey() + if err != nil { + return http.DefaultClient, ts, err + } + 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 { + return http.DefaultClient, ts, err + } + + session := Models.Session{ + UserID: u.ID, + Expiry: time.Now().Add(12 * time.Hour), + } + + err = Database.CreateSession(&session) + if err != nil { + return http.DefaultClient, ts, err + } + + jar, err := cookiejar.New(nil) + + url, _ := url.Parse(ts.URL) + + jar.SetCookies( + url, + []*http.Cookie{ + { + Name: "session_token", + Value: session.ID.String(), + MaxAge: 300, + }, + }, + ) + + client := &http.Client{ + Jar: jar, + } + + return client, ts, err +} diff --git a/Backend/go.mod b/Backend/go.mod index bebe75f..9db656c 100644 --- a/Backend/go.mod +++ b/Backend/go.mod @@ -3,7 +3,6 @@ module git.tovijaeschke.xyz/tovi/Capsule/Backend go 1.18 require ( - github.com/Kangaroux/go-map-schema v0.6.1 github.com/gofrs/uuid v4.2.0+incompatible github.com/gorilla/mux v1.8.0 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 diff --git a/test.sh b/test.sh index 66de839..dc285c9 100644 --- a/test.sh +++ b/test.sh @@ -1,3 +1,3 @@ #!/bin/sh -docker-compose exec server sh -c "cd /app && go test -v ./..." +docker-compose exec server sh -c "cd /app && go test -p 1 -v ./..."