| @ -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)) | |||
| } | |||
| } | |||
| @ -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 | |||
| } | |||
| } | |||
| @ -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 | |||
| } | |||
| } | |||
| @ -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 | |||
| } | |||
| @ -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 ./..." | |||