Reviewed-on: #4feature/add-notifications
@ -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 ./..." |