feature/dockerize-server into develop 3 years ago
| @ -0,0 +1,79 @@ | |||
| package Auth_test | |||
| import ( | |||
| "bytes" | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "net/http" | |||
| "os" | |||
| "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_AddProfileImage(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| key, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| dat, err := os.ReadFile("./profile_picture_test.png") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| encDat, err := key.AesEncrypt(dat) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| a := Models.Attachment{ | |||
| Mimetype: "image/png", | |||
| Extension: "png", | |||
| Data: base64.StdEncoding.EncodeToString(encDat), | |||
| } | |||
| jsonStr, _ := json.Marshal(a) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/image", 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 | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if u.AttachmentID.IsNil() { | |||
| t.Errorf("Attachment not assigned to user") | |||
| } | |||
| err = os.Remove("/app/attachments/" + u.Attachment.FilePath) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| } | |||
| @ -0,0 +1,89 @@ | |||
| package Auth_test | |||
| import ( | |||
| "bytes" | |||
| "encoding/json" | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_ChangeMessageExpiry(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| d := struct { | |||
| MessageExpiry string `json:"message_expiry"` | |||
| }{ | |||
| MessageExpiry: "fifteen_min", | |||
| } | |||
| jsonStr, _ := json.Marshal(d) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", 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) | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if u.MessageExpiryDefault.String() != "fifteen_min" { | |||
| t.Errorf("Failed to verify the MessageExpiryDefault has been changed") | |||
| } | |||
| } | |||
| func Test_ChangeMessageExpiryInvalidData(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| d := struct { | |||
| MessageExpiry string `json:"message_expiry"` | |||
| }{ | |||
| MessageExpiry: "invalid_message_expiry", | |||
| } | |||
| jsonStr, _ := json.Marshal(d) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", 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.StatusUnprocessableEntity { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode) | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if u.MessageExpiryDefault.String() != "no_expiry" { | |||
| t.Errorf("Failed to verify the MessageExpiryDefault has not been changed") | |||
| } | |||
| } | |||
| @ -0,0 +1,128 @@ | |||
| package Auth_test | |||
| import ( | |||
| "bytes" | |||
| "encoding/json" | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_ChangePassword(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| d := struct { | |||
| OldPassword string `json:"old_password"` | |||
| NewPassword string `json:"new_password"` | |||
| NewPasswordConfirm string `json:"new_password_confirm"` | |||
| PrivateKey string `json:"private_key"` | |||
| }{ | |||
| OldPassword: "password", | |||
| NewPassword: "password1", | |||
| NewPasswordConfirm: "password1", | |||
| PrivateKey: "", | |||
| } | |||
| jsonStr, _ := json.Marshal(d) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", 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 | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if !Auth.CheckPasswordHash("password1", u.Password) { | |||
| t.Errorf("Failed to verify the password has been changed") | |||
| } | |||
| } | |||
| func Test_ChangePasswordMismatchConfirmFails(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| d := struct { | |||
| OldPassword string `json:"old_password"` | |||
| NewPassword string `json:"new_password"` | |||
| NewPasswordConfirm string `json:"new_password_confirm"` | |||
| PrivateKey string `json:"private_key"` | |||
| }{ | |||
| OldPassword: "password", | |||
| NewPassword: "password1", | |||
| NewPasswordConfirm: "password2", | |||
| PrivateKey: "", | |||
| } | |||
| jsonStr, _ := json.Marshal(d) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", 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.StatusUnprocessableEntity { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode) | |||
| } | |||
| } | |||
| func Test_ChangePasswordInvalidCurrentPasswordFails(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| d := struct { | |||
| OldPassword string `json:"old_password"` | |||
| NewPassword string `json:"new_password"` | |||
| NewPasswordConfirm string `json:"new_password_confirm"` | |||
| PrivateKey string `json:"private_key"` | |||
| }{ | |||
| OldPassword: "password2", | |||
| NewPassword: "password1", | |||
| NewPasswordConfirm: "password1", | |||
| PrivateKey: "", | |||
| } | |||
| jsonStr, _ := json.Marshal(d) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", 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.StatusForbidden { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusForbidden, resp.StatusCode) | |||
| } | |||
| } | |||
| @ -0,0 +1,95 @@ | |||
| package Auth_test | |||
| import ( | |||
| "bytes" | |||
| "encoding/json" | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_Login(t *testing.T) { | |||
| _, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| 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 | |||
| } | |||
| 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 | |||
| if err != nil { | |||
| t.Errorf("Expected user record, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| } | |||
| func Test_Login_PasswordFails(t *testing.T) { | |||
| _, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| 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,44 @@ | |||
| package Auth_test | |||
| import ( | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_Logout(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| defer ts.Close() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| 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 | |||
| } | |||
| var session Models.Session | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected user record, recieved %s", err.Error()) | |||
| 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,87 @@ | |||
| package Friends | |||
| import ( | |||
| "encoding/json" | |||
| "io/ioutil" | |||
| "net/http" | |||
| "time" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| ) | |||
| // CreateFriendRequest creates a FriendRequest from post data | |||
| func CreateFriendRequest(w http.ResponseWriter, r *http.Request) { | |||
| var ( | |||
| friendRequest Models.FriendRequest | |||
| requestBody []byte | |||
| returnJSON []byte | |||
| err error | |||
| ) | |||
| requestBody, err = ioutil.ReadAll(r.Body) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| err = json.Unmarshal(requestBody, &friendRequest) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| friendRequest.AcceptedAt.Scan(nil) | |||
| err = Database.CreateFriendRequest(&friendRequest) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| returnJSON, err = json.MarshalIndent(friendRequest, "", " ") | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| // Return updated json | |||
| w.WriteHeader(http.StatusOK) | |||
| w.Write(returnJSON) | |||
| } | |||
| // CreateFriendRequestQrCode creates a FriendRequest from post data from qr code scan | |||
| func CreateFriendRequestQrCode(w http.ResponseWriter, r *http.Request) { | |||
| var ( | |||
| friendRequests []Models.FriendRequest | |||
| requestBody []byte | |||
| i int | |||
| err error | |||
| ) | |||
| requestBody, err = ioutil.ReadAll(r.Body) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| err = json.Unmarshal(requestBody, &friendRequests) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| for i = range friendRequests { | |||
| friendRequests[i].AcceptedAt.Time = time.Now() | |||
| friendRequests[i].AcceptedAt.Valid = true | |||
| } | |||
| err = Database.CreateFriendRequests(&friendRequests) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| // Return updated json | |||
| w.WriteHeader(http.StatusOK) | |||
| } | |||
| @ -1,41 +0,0 @@ | |||
| package Friends | |||
| import ( | |||
| "encoding/json" | |||
| "net/http" | |||
| "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Auth" | |||
| "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models" | |||
| ) | |||
| // EncryptedFriendRequestList gets friend request list | |||
| func EncryptedFriendRequestList(w http.ResponseWriter, r *http.Request) { | |||
| var ( | |||
| userSession Models.Session | |||
| friends []Models.FriendRequest | |||
| returnJSON []byte | |||
| err error | |||
| ) | |||
| userSession, err = Auth.CheckCookie(r) | |||
| if err != nil { | |||
| http.Error(w, "Forbidden", http.StatusUnauthorized) | |||
| return | |||
| } | |||
| friends, err = Database.GetFriendRequestsByUserID(userSession.UserID.String()) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| returnJSON, err = json.MarshalIndent(friends, "", " ") | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| w.WriteHeader(http.StatusOK) | |||
| w.Write(returnJSON) | |||
| } | |||
| @ -0,0 +1,124 @@ | |||
| package Friends_test | |||
| import ( | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "fmt" | |||
| "io/ioutil" | |||
| "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" | |||
| ) | |||
| func Test_FriendRequestList(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") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| for i := 0; i < 30; i++ { | |||
| u2, err := Tests.InitTestCreateUser(fmt.Sprintf("test%d", i)) | |||
| decodedPublicKey := Seeder.GetPubKey() | |||
| key, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| encPublicKey, err := key.AesEncrypt([]byte(Seeder.PublicKey)) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| friendReq := Models.FriendRequest{ | |||
| UserID: u.ID, | |||
| FriendID: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.ID.String()), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendUsername: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.Username), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendPublicAsymmetricKey: base64.StdEncoding.EncodeToString( | |||
| encPublicKey, | |||
| ), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(key.Key, decodedPublicKey), | |||
| ), | |||
| } | |||
| if i > 20 { | |||
| friendReq.AcceptedAt.Time = time.Now() | |||
| friendReq.AcceptedAt.Valid = true | |||
| } | |||
| err = Database.CreateFriendRequest(&friendReq) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| } | |||
| req, _ := http.NewRequest("GET", ts.URL+"/api/v1/auth/friend_requests", 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 users []Models.FriendRequest | |||
| json.Unmarshal(requestBody, &users) | |||
| if len(users) != 20 { | |||
| t.Errorf("Expected %d, recieved %d", 1, len(users)) | |||
| return | |||
| } | |||
| for i := 0; i < 20; i++ { | |||
| eq := true | |||
| if i > 8 { | |||
| eq = false | |||
| } | |||
| if users[i].AcceptedAt.Valid != eq { | |||
| t.Errorf( | |||
| "Expected %v, recieved %v, on user %d", | |||
| eq, users[i].AcceptedAt.Valid, | |||
| i, | |||
| ) | |||
| return | |||
| } | |||
| } | |||
| } | |||
| @ -1,76 +0,0 @@ | |||
| package JsonSerialization | |||
| import ( | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "strings" | |||
| "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models" | |||
| schema "github.com/Kangaroux/go-map-schema" | |||
| ) | |||
| func DeserializeUser(data []byte, allowMissing []string, allowAllMissing bool) (Models.User, error) { | |||
| var ( | |||
| userData Models.User = Models.User{} | |||
| jsonStructureTest map[string]interface{} = make(map[string]interface{}) | |||
| jsonStructureTestResults *schema.CompareResults | |||
| field schema.FieldMissing | |||
| allowed string | |||
| missingFields []string | |||
| i int | |||
| err error | |||
| ) | |||
| // Verify the JSON has the correct structure | |||
| json.Unmarshal(data, &jsonStructureTest) | |||
| jsonStructureTestResults, err = schema.CompareMapToStruct( | |||
| &userData, | |||
| jsonStructureTest, | |||
| &schema.CompareOpts{ | |||
| ConvertibleFunc: CanConvert, | |||
| TypeNameFunc: schema.DetailedTypeName, | |||
| }) | |||
| if err != nil { | |||
| return userData, err | |||
| } | |||
| if len(jsonStructureTestResults.MismatchedFields) > 0 { | |||
| return userData, errors.New(fmt.Sprintf( | |||
| "MismatchedFields found when deserializing data: %s", | |||
| jsonStructureTestResults.Errors().Error(), | |||
| )) | |||
| } | |||
| // Remove allowed missing fields from MissingFields | |||
| for _, allowed = range allowMissing { | |||
| for i, field = range jsonStructureTestResults.MissingFields { | |||
| if allowed == field.String() { | |||
| jsonStructureTestResults.MissingFields = append( | |||
| jsonStructureTestResults.MissingFields[:i], | |||
| jsonStructureTestResults.MissingFields[i+1:]..., | |||
| ) | |||
| } | |||
| } | |||
| } | |||
| if !allowAllMissing && len(jsonStructureTestResults.MissingFields) > 0 { | |||
| for _, field = range jsonStructureTestResults.MissingFields { | |||
| missingFields = append(missingFields, field.String()) | |||
| } | |||
| return userData, errors.New(fmt.Sprintf( | |||
| "MissingFields found when deserializing data: %s", | |||
| strings.Join(missingFields, ", "), | |||
| )) | |||
| } | |||
| // Deserialize the JSON into the struct | |||
| err = json.Unmarshal(data, &userData) | |||
| if err != nil { | |||
| return userData, err | |||
| } | |||
| return userData, err | |||
| } | |||
| @ -1,109 +0,0 @@ | |||
| package JsonSerialization | |||
| import ( | |||
| "math" | |||
| "reflect" | |||
| ) | |||
| // isIntegerType returns whether the type is an integer and if it's unsigned. | |||
| // See: https://github.com/Kangaroux/go-map-schema/blob/master/schema.go#L328 | |||
| func isIntegerType(t reflect.Type) (bool, bool) { | |||
| var ( | |||
| yes bool | |||
| unsigned bool | |||
| ) | |||
| switch t.Kind() { | |||
| case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |||
| yes = true | |||
| case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |||
| yes = true | |||
| unsigned = true | |||
| } | |||
| return yes, unsigned | |||
| } | |||
| // isFloatType returns true if the type is a floating point. Note that this doesn't | |||
| // care about the value -- unmarshaling the number "0" gives a float, not an int. | |||
| // See: https://github.com/Kangaroux/go-map-schema/blob/master/schema.go#L319 | |||
| func isFloatType(t reflect.Type) bool { | |||
| var ( | |||
| yes bool | |||
| ) | |||
| switch t.Kind() { | |||
| case reflect.Float32, reflect.Float64: | |||
| yes = true | |||
| } | |||
| return yes | |||
| } | |||
| // CanConvert returns whether value v is convertible to type t. | |||
| // | |||
| // If t is a pointer and v is not nil, it checks if v is convertible to the type that | |||
| // t points to. | |||
| // Modified due to not handling slices (DefaultCanConvert fails on PhotoUrls and Tags) | |||
| // See: https://github.com/Kangaroux/go-map-schema/blob/master/schema.go#L191 | |||
| func CanConvert(t reflect.Type, v reflect.Value) bool { | |||
| var ( | |||
| isPtr bool | |||
| isStruct bool | |||
| isArray bool | |||
| dstType reflect.Type | |||
| dstInt bool | |||
| unsigned bool | |||
| f float64 | |||
| srcInt bool | |||
| ) | |||
| isPtr = t.Kind() == reflect.Ptr | |||
| isStruct = t.Kind() == reflect.Struct | |||
| isArray = t.Kind() == reflect.Array | |||
| dstType = t | |||
| // Check if v is a nil value. | |||
| if !v.IsValid() || (v.CanAddr() && v.IsNil()) { | |||
| return isPtr | |||
| } | |||
| // If the dst is a pointer, check if we can convert to the type it's pointing to. | |||
| if isPtr { | |||
| dstType = t.Elem() | |||
| isStruct = t.Elem().Kind() == reflect.Struct | |||
| } | |||
| // If the dst is a struct, we should check its nested fields. | |||
| if isStruct { | |||
| return v.Kind() == reflect.Map | |||
| } | |||
| if isArray { | |||
| return v.Kind() == reflect.String | |||
| } | |||
| if t.Kind() == reflect.Slice { | |||
| return v.Kind() == reflect.Slice | |||
| } | |||
| if !v.Type().ConvertibleTo(dstType) { | |||
| return false | |||
| } | |||
| // Handle converting to an integer type. | |||
| dstInt, unsigned = isIntegerType(dstType) | |||
| if dstInt { | |||
| if isFloatType(v.Type()) { | |||
| f = v.Float() | |||
| if math.Trunc(f) != f || unsigned && f < 0 { | |||
| return false | |||
| } | |||
| } | |||
| srcInt, _ = isIntegerType(v.Type()) | |||
| if srcInt && unsigned && v.Int() < 0 { | |||
| return false | |||
| } | |||
| } | |||
| return true | |||
| } | |||
| @ -0,0 +1,256 @@ | |||
| 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)) | |||
| return | |||
| } | |||
| 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,128 @@ | |||
| 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,133 @@ | |||
| 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" | |||
| ) | |||
| // TODO: Write test for message expiry | |||
| 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,205 @@ | |||
| package Messages_test | |||
| import ( | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "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_Messages(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") | |||
| userKey, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| 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 | |||
| } | |||
| keyCiphertext, err := userKey.AesEncrypt( | |||
| []byte(base64.StdEncoding.EncodeToString(key.Key)), | |||
| ) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| pubKey := Seeder.GetPubKey() | |||
| message := Models.Message{ | |||
| MessageData: Models.MessageData{ | |||
| Data: base64.StdEncoding.EncodeToString(dataCiphertext), | |||
| SenderID: base64.StdEncoding.EncodeToString(senderIDCiphertext), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString(keyCiphertext), | |||
| }, | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||
| ), | |||
| AssociationKey: "AssociationKey", | |||
| } | |||
| err = Database.CreateMessage(&message) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| resp, err := client.Get(ts.URL + "/api/v1/auth/messages/AssociationKey") | |||
| 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 | |||
| } | |||
| requestBody, err := ioutil.ReadAll(resp.Body) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| var m []Models.Message | |||
| err = json.Unmarshal(requestBody, &m) | |||
| if len(m) != 1 { | |||
| t.Errorf("Expected %d, recieved %d", 1, len(m)) | |||
| } | |||
| msg := m[0] | |||
| decodedData, err := base64.StdEncoding.DecodeString(msg.MessageData.Data) | |||
| if err != nil { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||
| return | |||
| } | |||
| decrypedData, err := key.AesDecrypt(decodedData) | |||
| if err != nil { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||
| return | |||
| } | |||
| if string(decrypedData) != "Test message" { | |||
| t.Errorf("Expected %s, recieved %s", "Test converation", string(decrypedData)) | |||
| } | |||
| } | |||
| func Test_MessagesPagination(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") | |||
| userKey, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| 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 | |||
| } | |||
| keyCiphertext, err := userKey.AesEncrypt( | |||
| []byte(base64.StdEncoding.EncodeToString(key.Key)), | |||
| ) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| pubKey := Seeder.GetPubKey() | |||
| for i := 0; i < 50; i++ { | |||
| message := Models.Message{ | |||
| MessageData: Models.MessageData{ | |||
| Data: base64.StdEncoding.EncodeToString(dataCiphertext), | |||
| SenderID: base64.StdEncoding.EncodeToString(senderIDCiphertext), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString(keyCiphertext), | |||
| }, | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||
| ), | |||
| AssociationKey: "AssociationKey", | |||
| } | |||
| err = Database.CreateMessage(&message) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| } | |||
| resp, err := client.Get(ts.URL + "/api/v1/auth/messages/AssociationKey") | |||
| 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 | |||
| } | |||
| requestBody, err := ioutil.ReadAll(resp.Body) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| var m []Models.Message | |||
| err = json.Unmarshal(requestBody, &m) | |||
| if len(m) != 20 { | |||
| t.Errorf("Expected %d, recieved %d", 20, len(m)) | |||
| } | |||
| } | |||
| @ -0,0 +1,183 @@ | |||
| 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" | |||
| ) | |||
| func createConversation(key Seeder.AesKey) (Models.ConversationDetail, Models.UserConversation, Models.ConversationDetailUser, error) { | |||
| var ( | |||
| cd Models.ConversationDetail | |||
| uc Models.UserConversation | |||
| cdu Models.ConversationDetailUser | |||
| ) | |||
| u, err := Database.GetUserByUsername("test") | |||
| nameCiphertext, err := key.AesEncrypt([]byte("Test conversation")) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| twoUserCiphertext, err := key.AesEncrypt([]byte("false")) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| cd = Models.ConversationDetail{ | |||
| Name: base64.StdEncoding.EncodeToString(nameCiphertext), | |||
| TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext), | |||
| } | |||
| err = Database.CreateConversationDetail(&cd) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(cd.ID.String())) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| adminCiphertext, err := key.AesEncrypt([]byte("true")) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| pubKey := Seeder.GetPubKey() | |||
| uc = 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(&uc) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| userIDCiphertext, err := key.AesEncrypt([]byte(u.ID.String())) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| usernameCiphertext, err := key.AesEncrypt([]byte(u.Username)) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| adminCiphertext, err = key.AesEncrypt([]byte("true")) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| associationKeyCiphertext, err := key.AesEncrypt([]byte("association")) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| publicKeyCiphertext, err := key.AesEncrypt([]byte(u.AsymmetricPublicKey)) | |||
| if err != nil { | |||
| return cd, uc, cdu, err | |||
| } | |||
| cdu = Models.ConversationDetailUser{ | |||
| ConversationDetailID: cd.ID, | |||
| UserID: base64.StdEncoding.EncodeToString(userIDCiphertext), | |||
| Username: base64.StdEncoding.EncodeToString(usernameCiphertext), | |||
| Admin: base64.StdEncoding.EncodeToString(adminCiphertext), | |||
| AssociationKey: base64.StdEncoding.EncodeToString(associationKeyCiphertext), | |||
| PublicKey: base64.StdEncoding.EncodeToString(publicKeyCiphertext), | |||
| } | |||
| err = Database.CreateConversationDetailUser(&cdu) | |||
| return cd, uc, cdu, err | |||
| } | |||
| func Test_UpdateConversation(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 | |||
| } | |||
| cd, uc, cdu, err := createConversation(key) | |||
| nameCiphertext, err := key.AesEncrypt([]byte("Not test conversation")) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| } | |||
| d := struct { | |||
| ID string `json:"id"` | |||
| Name string `json:"name"` | |||
| Users []Models.ConversationDetailUser | |||
| UserConversations []Models.UserConversation | |||
| }{ | |||
| ID: cd.ID.String(), | |||
| Name: base64.StdEncoding.EncodeToString(nameCiphertext), | |||
| Users: []Models.ConversationDetailUser{ | |||
| cdu, | |||
| }, | |||
| UserConversations: []Models.UserConversation{ | |||
| uc, | |||
| }, | |||
| } | |||
| jsonStr, _ := json.Marshal(d) | |||
| req, _ := http.NewRequest("PUT", 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 ncd Models.ConversationDetail | |||
| err = Database.DB.First(&ncd, "id = ?", cd.ID.String()).Error | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| decodedName, err := base64.StdEncoding.DecodeString(ncd.Name) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| decrypedName, err := key.AesDecrypt(decodedName) | |||
| if err != nil { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||
| return | |||
| } | |||
| if string(decrypedName) != "Not test conversation" { | |||
| t.Errorf("Expected %s, recieved %s", "Not test converation", string(decrypedName)) | |||
| } | |||
| } | |||
| @ -0,0 +1,106 @@ | |||
| package Users_test | |||
| import ( | |||
| "encoding/json" | |||
| "fmt" | |||
| "io/ioutil" | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_SearchUsers(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u2, err := Tests.InitTestCreateUser("abcd") | |||
| req, _ := http.NewRequest( | |||
| "GET", | |||
| fmt.Sprintf("%s/api/v1/auth/users?username=%s", ts.URL, u2.Username), | |||
| 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 user Models.User | |||
| json.Unmarshal(requestBody, &user) | |||
| if user.Username != "abcd" { | |||
| t.Errorf("Expected abcd, recieved %s", user.Username) | |||
| return | |||
| } | |||
| if user.Password != "" { | |||
| t.Errorf("Expected \"\", recieved %s", user.Password) | |||
| return | |||
| } | |||
| if user.AsymmetricPrivateKey != "" { | |||
| t.Errorf("Expected \"\", recieved %s", user.AsymmetricPrivateKey) | |||
| return | |||
| } | |||
| } | |||
| func Test_SearchUsersPartialMatchFails(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| _, err = Tests.InitTestCreateUser("abcd") | |||
| req, _ := http.NewRequest( | |||
| "GET", | |||
| fmt.Sprintf("%s/api/v1/auth/users?username=%s", ts.URL, "abc"), | |||
| nil, | |||
| ) | |||
| resp, err := client.Do(req) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if resp.StatusCode != http.StatusNotFound { | |||
| 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 user interface{} | |||
| json.Unmarshal(requestBody, &user) | |||
| if user != nil { | |||
| t.Errorf("Expected nil, recieved %+v", user) | |||
| return | |||
| } | |||
| } | |||
| @ -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,92 @@ | |||
| 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" | |||
| ) | |||
| func InitTestCreateUser(username string) (Models.User, error) { | |||
| userKey, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| return Models.User{}, err | |||
| } | |||
| pubKey := Seeder.GetPubKey() | |||
| p, _ := Auth.HashPassword("password") | |||
| u := Models.User{ | |||
| Username: username, | |||
| Password: p, | |||
| AsymmetricPublicKey: Seeder.PublicKey, | |||
| AsymmetricPrivateKey: Seeder.EncryptedPrivateKey, | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(userKey.Key, pubKey), | |||
| ), | |||
| } | |||
| err = Database.CreateUser(&u) | |||
| return u, err | |||
| } | |||
| // 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) | |||
| u, err := InitTestCreateUser("test") | |||
| 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 | |||
| } | |||
| @ -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 -p 1 -v ./..." | |||