diff --git a/Backend/Api/Auth/AddProfileImage.go b/Backend/Api/Auth/AddProfileImage.go
index 31c7f64..af88ced 100644
--- a/Backend/Api/Auth/AddProfileImage.go
+++ b/Backend/Api/Auth/AddProfileImage.go
@@ -5,9 +5,9 @@ import (
"encoding/json"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Util"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Util"
)
// AddProfileImage adds a profile image
@@ -35,7 +35,17 @@ func AddProfileImage(w http.ResponseWriter, r *http.Request) {
}
decodedFile, err = base64.StdEncoding.DecodeString(attachment.Data)
+ if err != nil {
+ http.Error(w, "Error", http.StatusInternalServerError)
+ return
+ }
+
fileName, err = Util.WriteFile(decodedFile)
+ if err != nil {
+ http.Error(w, "Error", http.StatusInternalServerError)
+ return
+ }
+
attachment.FilePath = fileName
user.Attachment = attachment
diff --git a/Backend/Api/Auth/AddProfileImage_test.go b/Backend/Api/Auth/AddProfileImage_test.go
new file mode 100644
index 0000000..c0d0dc3
--- /dev/null
+++ b/Backend/Api/Auth/AddProfileImage_test.go
@@ -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
+ }
+}
diff --git a/Backend/Api/Auth/ChangeMessageExpiry.go b/Backend/Api/Auth/ChangeMessageExpiry.go
index acad218..aa2fd5e 100644
--- a/Backend/Api/Auth/ChangeMessageExpiry.go
+++ b/Backend/Api/Auth/ChangeMessageExpiry.go
@@ -5,8 +5,8 @@ import (
"io/ioutil"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
type rawChangeMessageExpiry struct {
@@ -37,7 +37,11 @@ func ChangeMessageExpiry(w http.ResponseWriter, r *http.Request) {
return
}
- user.MessageExpiryDefault.Scan(changeMessageExpiry.MessageExpiry)
+ err = user.MessageExpiryDefault.Scan(changeMessageExpiry.MessageExpiry)
+ if err != nil {
+ http.Error(w, "Error", http.StatusUnprocessableEntity)
+ return
+ }
err = Database.UpdateUser(
user.ID.String(),
@@ -48,5 +52,5 @@ func ChangeMessageExpiry(w http.ResponseWriter, r *http.Request) {
return
}
- w.WriteHeader(http.StatusOK)
+ w.WriteHeader(http.StatusNoContent)
}
diff --git a/Backend/Api/Auth/ChangeMessageExpiry_test.go b/Backend/Api/Auth/ChangeMessageExpiry_test.go
new file mode 100644
index 0000000..2c48c75
--- /dev/null
+++ b/Backend/Api/Auth/ChangeMessageExpiry_test.go
@@ -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")
+ }
+}
diff --git a/Backend/Api/Auth/ChangePassword.go b/Backend/Api/Auth/ChangePassword.go
index f4335cc..6e04bb5 100644
--- a/Backend/Api/Auth/ChangePassword.go
+++ b/Backend/Api/Auth/ChangePassword.go
@@ -5,8 +5,8 @@ import (
"io/ioutil"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
type rawChangePassword struct {
@@ -72,5 +72,5 @@ func ChangePassword(w http.ResponseWriter, r *http.Request) {
return
}
- w.WriteHeader(http.StatusOK)
+ w.WriteHeader(http.StatusNoContent)
}
diff --git a/Backend/Api/Auth/ChangePassword_test.go b/Backend/Api/Auth/ChangePassword_test.go
new file mode 100644
index 0000000..29c1e42
--- /dev/null
+++ b/Backend/Api/Auth/ChangePassword_test.go
@@ -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)
+ }
+}
diff --git a/Backend/Api/Auth/Login.go b/Backend/Api/Auth/Login.go
index d217493..7c72e07 100644
--- a/Backend/Api/Auth/Login.go
+++ b/Backend/Api/Auth/Login.go
@@ -6,8 +6,8 @@ import (
"net/http"
"time"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
type credentials struct {
diff --git a/Backend/Api/Auth/Login_test.go b/Backend/Api/Auth/Login_test.go
new file mode 100644
index 0000000..7eef436
--- /dev/null
+++ b/Backend/Api/Auth/Login_test.go
@@ -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
+ }
+}
diff --git a/Backend/Api/Auth/Logout.go b/Backend/Api/Auth/Logout.go
index 486b575..484fcc7 100644
--- a/Backend/Api/Auth/Logout.go
+++ b/Backend/Api/Auth/Logout.go
@@ -5,9 +5,10 @@ import (
"net/http"
"time"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
)
+// Logout logs out from system
func Logout(w http.ResponseWriter, r *http.Request) {
var (
c *http.Cookie
@@ -27,7 +28,7 @@ func Logout(w http.ResponseWriter, r *http.Request) {
sessionToken = c.Value
- err = Database.DeleteSessionById(sessionToken)
+ err = Database.DeleteSessionByID(sessionToken)
if err != nil {
log.Println("Could not delete session cookie")
}
@@ -37,4 +38,6 @@ func Logout(w http.ResponseWriter, r *http.Request) {
Value: "",
Expires: time.Now(),
})
+
+ w.WriteHeader(http.StatusOK)
}
diff --git a/Backend/Api/Auth/Logout_test.go b/Backend/Api/Auth/Logout_test.go
new file mode 100644
index 0000000..ca43f0c
--- /dev/null
+++ b/Backend/Api/Auth/Logout_test.go
@@ -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
+ }
+}
diff --git a/Backend/Api/Auth/Session.go b/Backend/Api/Auth/Session.go
index ffcfae2..4c4c5a1 100644
--- a/Backend/Api/Auth/Session.go
+++ b/Backend/Api/Auth/Session.go
@@ -4,8 +4,8 @@ import (
"errors"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
func CheckCookie(r *http.Request) (Models.Session, error) {
@@ -23,7 +23,7 @@ func CheckCookie(r *http.Request) (Models.Session, error) {
sessionToken = c.Value
// We then get the session from our session map
- userSession, err = Database.GetSessionById(sessionToken)
+ userSession, err = Database.GetSessionByID(sessionToken)
if err != nil {
return userSession, errors.New("Cookie not found")
}
diff --git a/Backend/Api/Auth/Signup.go b/Backend/Api/Auth/Signup.go
index b60f880..90252a9 100644
--- a/Backend/Api/Auth/Signup.go
+++ b/Backend/Api/Auth/Signup.go
@@ -2,95 +2,67 @@ package Auth
import (
"encoding/json"
- "io/ioutil"
- "log"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/JsonSerialization"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
-type signupResponse struct {
- Status string `json:"status"`
- Message string `json:"message"`
-}
-
-func makeSignupResponse(w http.ResponseWriter, code int, message string) {
- var (
- status = "error"
- returnJSON []byte
- err error
- )
- if code > 200 && code < 300 {
- status = "success"
- }
-
- returnJSON, err = json.MarshalIndent(signupResponse{
- Status: status,
- Message: message,
- }, "", " ")
- if err != nil {
- http.Error(w, "Error", http.StatusInternalServerError)
- return
- }
-
- // Return updated json
- w.WriteHeader(code)
- w.Write(returnJSON)
-
+type signup struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+ ConfirmPassword string `json:"confirm_password"`
+ PublicKey string `json:"asymmetric_public_key"`
+ PrivateKey string `json:"asymmetric_private_key"`
+ SymmetricKey string `json:"symmetric_key"`
}
// Signup to the platform
func Signup(w http.ResponseWriter, r *http.Request) {
var (
- userData Models.User
- requestBody []byte
- err error
+ user Models.User
+ err error
)
- requestBody, err = ioutil.ReadAll(r.Body)
+ err = json.NewDecoder(r.Body).Decode(&user)
if err != nil {
- log.Printf("Error encountered reading POST body: %s\n", err.Error())
- makeSignupResponse(w, http.StatusInternalServerError, "An error occurred")
+ http.Error(w, "Invalid Data", http.StatusUnprocessableEntity)
return
}
- userData, err = JsonSerialization.DeserializeUser(requestBody, []string{
- "id",
- }, false)
- if err != nil {
- log.Printf("Invalid data provided to Signup: %s\n", err.Error())
- makeSignupResponse(w, http.StatusUnprocessableEntity, "Invalid data provided")
+ if user.Username == "" ||
+ user.Password == "" ||
+ user.ConfirmPassword == "" ||
+ len(user.AsymmetricPrivateKey) == 0 ||
+ len(user.AsymmetricPublicKey) == 0 ||
+ len(user.SymmetricKey) == 0 {
+
+ http.Error(w, "Invalid Data", http.StatusUnprocessableEntity)
return
}
- if userData.Username == "" ||
- userData.Password == "" ||
- userData.ConfirmPassword == "" ||
- len(userData.AsymmetricPrivateKey) == 0 ||
- len(userData.AsymmetricPublicKey) == 0 {
- makeSignupResponse(w, http.StatusUnprocessableEntity, "Invalid data provided")
+ if user.Password != user.ConfirmPassword {
+ http.Error(w, "Invalid Data", http.StatusUnprocessableEntity)
return
}
- err = Database.CheckUniqueUsername(userData.Username)
+ err = Database.CheckUniqueUsername(user.Username)
if err != nil {
- makeSignupResponse(w, http.StatusUnprocessableEntity, "Invalid data provided")
+ http.Error(w, "Invalid Data", http.StatusUnprocessableEntity)
return
}
- userData.Password, err = HashPassword(userData.Password)
+ user.Password, err = HashPassword(user.Password)
if err != nil {
- makeSignupResponse(w, http.StatusInternalServerError, "An error occurred")
+ http.Error(w, "Error", http.StatusInternalServerError)
return
}
- err = Database.CreateUser(&userData)
+ err = Database.CreateUser(&user)
if err != nil {
- makeSignupResponse(w, http.StatusInternalServerError, "An error occurred")
+ http.Error(w, "Error", http.StatusInternalServerError)
return
}
- makeSignupResponse(w, http.StatusCreated, "Successfully signed up")
+ w.WriteHeader(http.StatusNoContent)
}
diff --git a/Backend/Api/Auth/Signup_test.go b/Backend/Api/Auth/Signup_test.go
new file mode 100644
index 0000000..c57b125
--- /dev/null
+++ b/Backend/Api/Auth/Signup_test.go
@@ -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)
+ }
+}
diff --git a/Backend/Api/Auth/profile_picture_test.png b/Backend/Api/Auth/profile_picture_test.png
new file mode 100644
index 0000000..bec7dbc
Binary files /dev/null and b/Backend/Api/Auth/profile_picture_test.png differ
diff --git a/Backend/Api/Friends/AcceptFriendRequest.go b/Backend/Api/Friends/AcceptFriendRequest.go
index aa9e233..9b68bdd 100644
--- a/Backend/Api/Friends/AcceptFriendRequest.go
+++ b/Backend/Api/Friends/AcceptFriendRequest.go
@@ -6,8 +6,8 @@ import (
"net/http"
"time"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
diff --git a/Backend/Api/Friends/CreateFriendRequest.go b/Backend/Api/Friends/CreateFriendRequest.go
new file mode 100644
index 0000000..d7f0b53
--- /dev/null
+++ b/Backend/Api/Friends/CreateFriendRequest.go
@@ -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)
+}
diff --git a/Backend/Api/Friends/EncryptedFriendsList.go b/Backend/Api/Friends/EncryptedFriendsList.go
deleted file mode 100644
index 410c75c..0000000
--- a/Backend/Api/Friends/EncryptedFriendsList.go
+++ /dev/null
@@ -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)
-}
diff --git a/Backend/Api/Friends/FriendRequest.go b/Backend/Api/Friends/FriendRequest.go
index 126605d..c704800 100644
--- a/Backend/Api/Friends/FriendRequest.go
+++ b/Backend/Api/Friends/FriendRequest.go
@@ -5,9 +5,9 @@ import (
"io/ioutil"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Util"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Util"
)
func FriendRequest(w http.ResponseWriter, r *http.Request) {
diff --git a/Backend/Api/Friends/Friends.go b/Backend/Api/Friends/Friends.go
index a1db196..3bd58ba 100644
--- a/Backend/Api/Friends/Friends.go
+++ b/Backend/Api/Friends/Friends.go
@@ -2,86 +2,47 @@ package Friends
import (
"encoding/json"
- "io/ioutil"
"net/http"
- "time"
+ "net/url"
+ "strconv"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
+ "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) {
+// FriendRequestList gets friend request list
+func FriendRequestList(w http.ResponseWriter, r *http.Request) {
var (
- friendRequest Models.FriendRequest
- requestBody []byte
- returnJSON []byte
- err error
+ userSession Models.Session
+ friends []Models.FriendRequest
+ values url.Values
+ returnJSON []byte
+ page int
+ err error
)
- requestBody, err = ioutil.ReadAll(r.Body)
- if err != nil {
- http.Error(w, "Error", http.StatusInternalServerError)
- return
- }
+ values = r.URL.Query()
- err = json.Unmarshal(requestBody, &friendRequest)
+ page, err = strconv.Atoi(values.Get("page"))
if err != nil {
- http.Error(w, "Error", http.StatusInternalServerError)
- return
+ page = 0
}
- friendRequest.AcceptedAt.Scan(nil)
+ userSession, _ = Auth.CheckCookie(r)
- err = Database.CreateFriendRequest(&friendRequest)
+ friends, err = Database.GetFriendRequestsByUserID(userSession.UserID.String(), page)
if err != nil {
http.Error(w, "Error", http.StatusInternalServerError)
return
}
- returnJSON, err = json.MarshalIndent(friendRequest, "", " ")
+ returnJSON, err = json.MarshalIndent(friends, "", " ")
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)
-}
diff --git a/Backend/Api/Friends/Friends_test.go b/Backend/Api/Friends/Friends_test.go
new file mode 100644
index 0000000..d18de12
--- /dev/null
+++ b/Backend/Api/Friends/Friends_test.go
@@ -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
+ }
+ }
+}
diff --git a/Backend/Api/Friends/RejectFriendRequest.go b/Backend/Api/Friends/RejectFriendRequest.go
index e341858..8ba5829 100644
--- a/Backend/Api/Friends/RejectFriendRequest.go
+++ b/Backend/Api/Friends/RejectFriendRequest.go
@@ -3,8 +3,8 @@ package Friends
import (
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
diff --git a/Backend/Api/JsonSerialization/DeserializeUserJson.go b/Backend/Api/JsonSerialization/DeserializeUserJson.go
deleted file mode 100644
index 9220be8..0000000
--- a/Backend/Api/JsonSerialization/DeserializeUserJson.go
+++ /dev/null
@@ -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
-}
diff --git a/Backend/Api/JsonSerialization/VerifyJson.go b/Backend/Api/JsonSerialization/VerifyJson.go
deleted file mode 100644
index 3a3ae78..0000000
--- a/Backend/Api/JsonSerialization/VerifyJson.go
+++ /dev/null
@@ -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
-}
diff --git a/Backend/Api/Messages/AddConversationImage.go b/Backend/Api/Messages/AddConversationImage.go
index 1da2866..31c36e9 100644
--- a/Backend/Api/Messages/AddConversationImage.go
+++ b/Backend/Api/Messages/AddConversationImage.go
@@ -5,9 +5,9 @@ import (
"encoding/json"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Util"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Util"
"github.com/gorilla/mux"
)
diff --git a/Backend/Api/Messages/Conversations.go b/Backend/Api/Messages/Conversations.go
index a1681da..1639111 100644
--- a/Backend/Api/Messages/Conversations.go
+++ b/Backend/Api/Messages/Conversations.go
@@ -4,30 +4,37 @@ import (
"encoding/json"
"net/http"
"net/url"
+ "strconv"
"strings"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Auth"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
-// EncryptedConversationList returns an encrypted list of all Conversations
-func EncryptedConversationList(w http.ResponseWriter, r *http.Request) {
+// ConversationList returns an encrypted list of all Conversations
+func ConversationList(w http.ResponseWriter, r *http.Request) {
var (
conversationDetails []Models.UserConversation
userSession Models.Session
returnJSON []byte
+ values url.Values
+ page int
err error
)
- userSession, err = Auth.CheckCookie(r)
+ values = r.URL.Query()
+
+ page, err = strconv.Atoi(values.Get("page"))
if err != nil {
- http.Error(w, "Forbidden", http.StatusUnauthorized)
- return
+ page = 0
}
+ userSession, _ = Auth.CheckCookie(r)
+
conversationDetails, err = Database.GetUserConversationsByUserId(
userSession.UserID.String(),
+ page,
)
if err != nil {
http.Error(w, "Error", http.StatusInternalServerError)
@@ -44,8 +51,8 @@ func EncryptedConversationList(w http.ResponseWriter, r *http.Request) {
w.Write(returnJSON)
}
-// EncryptedConversationDetailsList returns an encrypted list of all ConversationDetails
-func EncryptedConversationDetailsList(w http.ResponseWriter, r *http.Request) {
+// ConversationDetailsList returns an encrypted list of all ConversationDetails
+func ConversationDetailsList(w http.ResponseWriter, r *http.Request) {
var (
conversationDetails []Models.ConversationDetail
detail Models.ConversationDetail
diff --git a/Backend/Api/Messages/Conversations_test.go b/Backend/Api/Messages/Conversations_test.go
new file mode 100644
index 0000000..49f3654
--- /dev/null
+++ b/Backend/Api/Messages/Conversations_test.go
@@ -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))
+ }
+}
diff --git a/Backend/Api/Messages/CreateConversation.go b/Backend/Api/Messages/CreateConversation.go
index 41de38c..12d54e1 100644
--- a/Backend/Api/Messages/CreateConversation.go
+++ b/Backend/Api/Messages/CreateConversation.go
@@ -6,8 +6,8 @@ import (
"github.com/gofrs/uuid"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
// RawCreateConversationData for holding POST payload
@@ -54,5 +54,5 @@ func CreateConversation(w http.ResponseWriter, r *http.Request) {
return
}
- w.WriteHeader(http.StatusOK)
+ w.WriteHeader(http.StatusNoContent)
}
diff --git a/Backend/Api/Messages/CreateConversation_test.go b/Backend/Api/Messages/CreateConversation_test.go
new file mode 100644
index 0000000..5659dff
--- /dev/null
+++ b/Backend/Api/Messages/CreateConversation_test.go
@@ -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
+ }
+}
diff --git a/Backend/Api/Messages/CreateMessage.go b/Backend/Api/Messages/CreateMessage.go
index 052f128..04cb15e 100644
--- a/Backend/Api/Messages/CreateMessage.go
+++ b/Backend/Api/Messages/CreateMessage.go
@@ -4,10 +4,11 @@ import (
"encoding/base64"
"encoding/json"
"net/http"
+ "time"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Util"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Util"
)
type rawMessageData struct {
@@ -20,8 +21,11 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) {
var (
messagesData []rawMessageData
messageData rawMessageData
+ message Models.Message
+ t time.Time
decodedFile []byte
fileName string
+ i int
err error
)
@@ -38,6 +42,19 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) {
messageData.MessageData.Attachment.FilePath = fileName
}
+ for i, message = range messageData.Messages {
+ t, err = time.Parse("2006-01-02T15:04:05Z", message.ExpiryRaw)
+ if err != nil {
+ http.Error(w, "Error", http.StatusInternalServerError)
+ return
+ }
+ err = messageData.Messages[i].Expiry.Scan(t)
+ if err != nil {
+ http.Error(w, "Error", http.StatusInternalServerError)
+ return
+ }
+ }
+
err = Database.CreateMessageData(&messageData.MessageData)
if err != nil {
http.Error(w, "Error", http.StatusInternalServerError)
@@ -51,5 +68,5 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) {
}
}
- w.WriteHeader(http.StatusOK)
+ w.WriteHeader(http.StatusNoContent)
}
diff --git a/Backend/Api/Messages/CreateMessage_test.go b/Backend/Api/Messages/CreateMessage_test.go
new file mode 100644
index 0000000..81666c5
--- /dev/null
+++ b/Backend/Api/Messages/CreateMessage_test.go
@@ -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
+ }
+
+}
diff --git a/Backend/Api/Messages/MessageThread.go b/Backend/Api/Messages/MessageThread.go
index 686f1c1..1135c20 100644
--- a/Backend/Api/Messages/MessageThread.go
+++ b/Backend/Api/Messages/MessageThread.go
@@ -3,9 +3,11 @@ package Messages
import (
"encoding/json"
"net/http"
+ "net/url"
+ "strconv"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
@@ -17,7 +19,9 @@ func Messages(w http.ResponseWriter, r *http.Request) {
message Models.Message
urlVars map[string]string
associationKey string
+ values url.Values
returnJSON []byte
+ page int
i int
ok bool
err error
@@ -30,7 +34,14 @@ func Messages(w http.ResponseWriter, r *http.Request) {
return
}
- messages, err = Database.GetMessagesByAssociationKey(associationKey)
+ values = r.URL.Query()
+
+ page, err = strconv.Atoi(values.Get("page"))
+ if err != nil {
+ page = 0
+ }
+
+ messages, err = Database.GetMessagesByAssociationKey(associationKey, page)
if !ok {
http.Error(w, "Not Found", http.StatusNotFound)
return
diff --git a/Backend/Api/Messages/MessageThread_test.go b/Backend/Api/Messages/MessageThread_test.go
new file mode 100644
index 0000000..bf4325e
--- /dev/null
+++ b/Backend/Api/Messages/MessageThread_test.go
@@ -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))
+ }
+}
diff --git a/Backend/Api/Messages/UpdateConversation.go b/Backend/Api/Messages/UpdateConversation.go
index 4900ba8..67d2a2c 100644
--- a/Backend/Api/Messages/UpdateConversation.go
+++ b/Backend/Api/Messages/UpdateConversation.go
@@ -6,8 +6,8 @@ import (
"github.com/gofrs/uuid"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
type rawUpdateConversationData struct {
diff --git a/Backend/Api/Messages/UpdateConversation_test.go b/Backend/Api/Messages/UpdateConversation_test.go
new file mode 100644
index 0000000..cdc3684
--- /dev/null
+++ b/Backend/Api/Messages/UpdateConversation_test.go
@@ -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))
+ }
+
+}
diff --git a/Backend/Api/Routes.go b/Backend/Api/Routes.go
index 8b0c280..73d98f4 100644
--- a/Backend/Api/Routes.go
+++ b/Backend/Api/Routes.go
@@ -4,10 +4,10 @@ import (
"log"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Auth"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Friends"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Messages"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Users"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Friends"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Messages"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Users"
"github.com/gorilla/mux"
)
@@ -68,14 +68,14 @@ func InitAPIEndpoints(router *mux.Router) {
authAPI.HandleFunc("/users", Users.SearchUsers).Methods("GET")
- authAPI.HandleFunc("/friend_requests", Friends.EncryptedFriendRequestList).Methods("GET")
+ authAPI.HandleFunc("/friend_requests", Friends.FriendRequestList).Methods("GET")
authAPI.HandleFunc("/friend_request", Friends.CreateFriendRequest).Methods("POST")
authAPI.HandleFunc("/friend_request/qr_code", Friends.CreateFriendRequestQrCode).Methods("POST")
authAPI.HandleFunc("/friend_request/{requestID}", Friends.AcceptFriendRequest).Methods("POST")
authAPI.HandleFunc("/friend_request/{requestID}", Friends.RejectFriendRequest).Methods("DELETE")
- authAPI.HandleFunc("/conversations", Messages.EncryptedConversationList).Methods("GET")
- authAPI.HandleFunc("/conversation_details", Messages.EncryptedConversationDetailsList).Methods("GET")
+ authAPI.HandleFunc("/conversations", Messages.ConversationList).Methods("GET")
+ authAPI.HandleFunc("/conversation_details", Messages.ConversationDetailsList).Methods("GET")
authAPI.HandleFunc("/conversations", Messages.CreateConversation).Methods("POST")
authAPI.HandleFunc("/conversations", Messages.UpdateConversation).Methods("PUT")
authAPI.HandleFunc("/conversations/{detailID}/image", Messages.AddConversationImage).Methods("POST")
diff --git a/Backend/Api/Users/SearchUsers.go b/Backend/Api/Users/SearchUsers.go
index 56ecd89..a073749 100644
--- a/Backend/Api/Users/SearchUsers.go
+++ b/Backend/Api/Users/SearchUsers.go
@@ -5,8 +5,8 @@ import (
"net/http"
"net/url"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
// SearchUsers searches a for a user by username
@@ -46,7 +46,6 @@ func SearchUsers(w http.ResponseWriter, r *http.Request) {
returnJSON, err = json.MarshalIndent(user, "", " ")
if err != nil {
- panic(err)
http.Error(w, "Not Found", http.StatusNotFound)
return
}
diff --git a/Backend/Api/Users/SearchUsers_test.go b/Backend/Api/Users/SearchUsers_test.go
new file mode 100644
index 0000000..1b018f3
--- /dev/null
+++ b/Backend/Api/Users/SearchUsers_test.go
@@ -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
+ }
+}
diff --git a/Backend/Database/Attachments.go b/Backend/Database/Attachments.go
index 3097a04..bda1415 100644
--- a/Backend/Database/Attachments.go
+++ b/Backend/Database/Attachments.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
diff --git a/Backend/Database/ConversationDetailUsers.go b/Backend/Database/ConversationDetailUsers.go
index 6396acb..9215c0f 100644
--- a/Backend/Database/ConversationDetailUsers.go
+++ b/Backend/Database/ConversationDetailUsers.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
diff --git a/Backend/Database/ConversationDetails.go b/Backend/Database/ConversationDetails.go
index af04edb..811fa62 100644
--- a/Backend/Database/ConversationDetails.go
+++ b/Backend/Database/ConversationDetails.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
diff --git a/Backend/Database/FriendRequests.go b/Backend/Database/FriendRequests.go
index 0f6e58a..951a7a1 100644
--- a/Backend/Database/FriendRequests.go
+++ b/Backend/Database/FriendRequests.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -22,14 +22,20 @@ func GetFriendRequestByID(id string) (Models.FriendRequest, error) {
}
// GetFriendRequestsByUserID gets friend request by user id
-func GetFriendRequestsByUserID(userID string) ([]Models.FriendRequest, error) {
+func GetFriendRequestsByUserID(userID string, page int) ([]Models.FriendRequest, error) {
var (
friends []Models.FriendRequest
+ offset int
err error
)
+ offset = page * PageSize
+
err = DB.Model(Models.FriendRequest{}).
Where("user_id = ?", userID).
+ Offset(offset).
+ Limit(PageSize).
+ Order("created_at DESC").
Find(&friends).
Error
diff --git a/Backend/Database/Init.go b/Backend/Database/Init.go
index f4b6fb9..982a7d4 100644
--- a/Backend/Database/Init.go
+++ b/Backend/Database/Init.go
@@ -3,39 +3,38 @@ package Database
import (
"log"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
const (
- dbURL = "postgres://postgres:@localhost:5432/envelope"
- dbTestURL = "postgres://postgres:@localhost:5432/envelope_test"
+ dbURL = "postgres://postgres:password@postgres:5432/capsule"
+ dbTestURL = "postgres://postgres:password@postgres-testing:5432/capsule-testing"
+
+ PageSize = 20
)
// DB db
var DB *gorm.DB
-func getModels() []interface{} {
- return []interface{}{
- &Models.Session{},
- &Models.Attachment{},
- &Models.User{},
- &Models.FriendRequest{},
- &Models.MessageData{},
- &Models.Message{},
- &Models.ConversationDetail{},
- &Models.ConversationDetailUser{},
- &Models.UserConversation{},
- }
+var models = []interface{}{
+ &Models.Session{},
+ &Models.Attachment{},
+ &Models.User{},
+ &Models.FriendRequest{},
+ &Models.MessageData{},
+ &Models.Message{},
+ &Models.ConversationDetail{},
+ &Models.ConversationDetailUser{},
+ &Models.UserConversation{},
}
// Init initializes the database connection
func Init() {
var (
- model interface{}
- err error
+ err error
)
log.Println("Initializing database...")
@@ -48,19 +47,16 @@ func Init() {
log.Println("Running AutoMigrate...")
- for _, model = range getModels() {
- err = DB.AutoMigrate(model)
- if err != nil {
- log.Fatalln(err)
- }
+ err = DB.AutoMigrate(models...)
+ if err != nil {
+ log.Fatalln(err)
}
}
// InitTest initializes the test datbase
func InitTest() {
var (
- model interface{}
- err error
+ err error
)
DB, err = gorm.Open(postgres.Open(dbTestURL), &gorm.Config{})
@@ -69,8 +65,12 @@ func InitTest() {
log.Fatalln(err)
}
- for _, model = range getModels() {
- DB.Migrator().DropTable(model)
- DB.AutoMigrate(model)
+ err = DB.Migrator().DropTable(models...)
+ if err != nil {
+ panic(err)
+ }
+ err = DB.AutoMigrate(models...)
+ if err != nil {
+ panic(err)
}
}
diff --git a/Backend/Database/MessageData.go b/Backend/Database/MessageData.go
index 80c6515..4198f2a 100644
--- a/Backend/Database/MessageData.go
+++ b/Backend/Database/MessageData.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
diff --git a/Backend/Database/Messages.go b/Backend/Database/Messages.go
index f415c0e..37d0c14 100644
--- a/Backend/Database/Messages.go
+++ b/Backend/Database/Messages.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -22,15 +22,20 @@ func GetMessageByID(id string) (Models.Message, error) {
}
// GetMessagesByAssociationKey for getting whole thread
-// TODO: Add pagination
-func GetMessagesByAssociationKey(associationKey string) ([]Models.Message, error) {
+func GetMessagesByAssociationKey(associationKey string, page int) ([]Models.Message, error) {
var (
messages []Models.Message
+ offset int
err error
)
+ offset = page * PageSize
+
err = DB.Preload("MessageData").
Preload("MessageData.Attachment").
+ Offset(offset).
+ Limit(PageSize).
+ Order("created_at DESC").
Find(&messages, "association_key = ?", associationKey).
Error
diff --git a/Backend/Database/Seeder/FriendSeeder.go b/Backend/Database/Seeder/FriendSeeder.go
index e317d13..43cdd0f 100644
--- a/Backend/Database/Seeder/FriendSeeder.go
+++ b/Backend/Database/Seeder/FriendSeeder.go
@@ -6,24 +6,24 @@ import (
"os"
"time"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
func seedFriend(userRequestTo, userRequestFrom Models.User, accepted bool) error {
var (
friendRequest Models.FriendRequest
- symKey aesKey
+ symKey AesKey
encPublicKey []byte
err error
)
- symKey, err = generateAesKey()
+ symKey, err = GenerateAesKey()
if err != nil {
return err
}
- encPublicKey, err = symKey.aesEncrypt([]byte(publicKey))
+ encPublicKey, err = symKey.AesEncrypt([]byte(PublicKey))
if err != nil {
return err
}
@@ -31,13 +31,13 @@ func seedFriend(userRequestTo, userRequestFrom Models.User, accepted bool) error
friendRequest = Models.FriendRequest{
UserID: userRequestTo.ID,
FriendID: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(
+ EncryptWithPublicKey(
[]byte(userRequestFrom.ID.String()),
decodedPublicKey,
),
),
FriendUsername: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(
+ EncryptWithPublicKey(
[]byte(userRequestFrom.Username),
decodedPublicKey,
),
@@ -46,7 +46,7 @@ func seedFriend(userRequestTo, userRequestFrom Models.User, accepted bool) error
encPublicKey,
),
SymmetricKey: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(symKey.Key, decodedPublicKey),
+ EncryptWithPublicKey(symKey.Key, decodedPublicKey),
),
}
diff --git a/Backend/Database/Seeder/MessageSeeder.go b/Backend/Database/Seeder/MessageSeeder.go
index 1bdffb9..a117742 100644
--- a/Backend/Database/Seeder/MessageSeeder.go
+++ b/Backend/Database/Seeder/MessageSeeder.go
@@ -3,8 +3,8 @@ package Seeder
import (
"encoding/base64"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gofrs/uuid"
)
@@ -17,7 +17,7 @@ func seedMessage(
var (
message Models.Message
messageData Models.MessageData
- key, userKey aesKey
+ key, userKey AesKey
keyCiphertext []byte
plaintext string
dataCiphertext []byte
@@ -27,34 +27,34 @@ func seedMessage(
plaintext = "Test Message"
- userKey, err = generateAesKey()
+ userKey, err = GenerateAesKey()
if err != nil {
panic(err)
}
- key, err = generateAesKey()
+ key, err = GenerateAesKey()
if err != nil {
panic(err)
}
- dataCiphertext, err = key.aesEncrypt([]byte(plaintext))
+ dataCiphertext, err = key.AesEncrypt([]byte(plaintext))
if err != nil {
panic(err)
}
- senderIDCiphertext, err = key.aesEncrypt([]byte(primaryUser.ID.String()))
+ senderIDCiphertext, err = key.AesEncrypt([]byte(primaryUser.ID.String()))
if err != nil {
panic(err)
}
if i%2 == 0 {
- senderIDCiphertext, err = key.aesEncrypt([]byte(secondaryUser.ID.String()))
+ senderIDCiphertext, err = key.AesEncrypt([]byte(secondaryUser.ID.String()))
if err != nil {
panic(err)
}
}
- keyCiphertext, err = userKey.aesEncrypt(
+ keyCiphertext, err = userKey.AesEncrypt(
[]byte(base64.StdEncoding.EncodeToString(key.Key)),
)
if err != nil {
@@ -70,7 +70,7 @@ func seedMessage(
message = Models.Message{
MessageData: messageData,
SymmetricKey: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(userKey.Key, decodedPublicKey),
+ EncryptWithPublicKey(userKey.Key, decodedPublicKey),
),
AssociationKey: primaryUserAssociationKey,
}
@@ -83,7 +83,7 @@ func seedMessage(
message = Models.Message{
MessageData: messageData,
SymmetricKey: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(userKey.Key, decodedPublicKey),
+ EncryptWithPublicKey(userKey.Key, decodedPublicKey),
),
AssociationKey: secondaryUserAssociationKey,
}
@@ -91,7 +91,7 @@ func seedMessage(
return Database.CreateMessage(&message)
}
-func seedConversationDetail(key aesKey) (Models.ConversationDetail, error) {
+func seedConversationDetail(key AesKey) (Models.ConversationDetail, error) {
var (
messageThread Models.ConversationDetail
name string
@@ -102,12 +102,12 @@ func seedConversationDetail(key aesKey) (Models.ConversationDetail, error) {
name = "Test Conversation"
- nameCiphertext, err = key.aesEncrypt([]byte(name))
+ nameCiphertext, err = key.AesEncrypt([]byte(name))
if err != nil {
panic(err)
}
- twoUserCiphertext, err = key.aesEncrypt([]byte("false"))
+ twoUserCiphertext, err = key.AesEncrypt([]byte("false"))
if err != nil {
panic(err)
}
@@ -124,7 +124,7 @@ func seedConversationDetail(key aesKey) (Models.ConversationDetail, error) {
func seedUserConversation(
user Models.User,
threadID uuid.UUID,
- key aesKey,
+ key AesKey,
) (Models.UserConversation, error) {
var (
messageThreadUser Models.UserConversation
@@ -133,12 +133,12 @@ func seedUserConversation(
err error
)
- conversationDetailIDCiphertext, err = key.aesEncrypt([]byte(threadID.String()))
+ conversationDetailIDCiphertext, err = key.AesEncrypt([]byte(threadID.String()))
if err != nil {
return messageThreadUser, err
}
- adminCiphertext, err = key.aesEncrypt([]byte("true"))
+ adminCiphertext, err = key.AesEncrypt([]byte("true"))
if err != nil {
return messageThreadUser, err
}
@@ -148,7 +148,7 @@ func seedUserConversation(
ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext),
Admin: base64.StdEncoding.EncodeToString(adminCiphertext),
SymmetricKey: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(key.Key, decodedPublicKey),
+ EncryptWithPublicKey(key.Key, decodedPublicKey),
),
}
@@ -161,7 +161,7 @@ func seedConversationDetailUser(
conversationDetail Models.ConversationDetail,
associationKey uuid.UUID,
admin bool,
- key aesKey,
+ key AesKey,
) (Models.ConversationDetailUser, error) {
var (
conversationDetailUser Models.ConversationDetailUser
@@ -181,27 +181,27 @@ func seedConversationDetailUser(
adminString = "true"
}
- userIDCiphertext, err = key.aesEncrypt([]byte(user.ID.String()))
+ userIDCiphertext, err = key.AesEncrypt([]byte(user.ID.String()))
if err != nil {
return conversationDetailUser, err
}
- usernameCiphertext, err = key.aesEncrypt([]byte(user.Username))
+ usernameCiphertext, err = key.AesEncrypt([]byte(user.Username))
if err != nil {
return conversationDetailUser, err
}
- adminCiphertext, err = key.aesEncrypt([]byte(adminString))
+ adminCiphertext, err = key.AesEncrypt([]byte(adminString))
if err != nil {
return conversationDetailUser, err
}
- associationKeyCiphertext, err = key.aesEncrypt([]byte(associationKey.String()))
+ associationKeyCiphertext, err = key.AesEncrypt([]byte(associationKey.String()))
if err != nil {
return conversationDetailUser, err
}
- publicKeyCiphertext, err = key.aesEncrypt([]byte(user.AsymmetricPublicKey))
+ publicKeyCiphertext, err = key.AesEncrypt([]byte(user.AsymmetricPublicKey))
if err != nil {
return conversationDetailUser, err
}
@@ -224,7 +224,7 @@ func seedConversationDetailUser(
func SeedMessages() {
var (
conversationDetail Models.ConversationDetail
- key aesKey
+ key AesKey
primaryUser Models.User
primaryUserAssociationKey uuid.UUID
secondaryUser Models.User
@@ -233,7 +233,7 @@ func SeedMessages() {
err error
)
- key, err = generateAesKey()
+ key, err = GenerateAesKey()
if err != nil {
panic(err)
}
diff --git a/Backend/Database/Seeder/Seed.go b/Backend/Database/Seeder/Seed.go
index 7bd5c40..bdfc1d0 100644
--- a/Backend/Database/Seeder/Seed.go
+++ b/Backend/Database/Seeder/Seed.go
@@ -9,11 +9,11 @@ import (
)
const (
- // Encrypted with "password"
- encryptedPrivateKey string = `sPhQsHpXYFqPb7qdmTY7APFwBb4m7meCITujDeKMQFnIjplOVm9ijjXU+YAmGvrX13ukBj8zo9MTVhjJUjJ917pyLhl4w8uyg1jCvplUYtJVXhGA9Wy3NqHMuq3SU3fKdlEM+oR4zYkbAYWp42XvulbcuVBEWiWkvHOrbdKPFpMmd54SL2c/vcWrmjgC7rTlJf2TYICZwRK+6Y0XZi5fSWeU0vg7+rHWKHc5MHHtAdAiL+HCa90c5gfh+hXkT5ojGHOkhT9kdLy3PTPN19EGpdXgZ3WFq1z9CZ6zX7uM091uR0IvgzfwaLx8HJCx7ViWQhioH9LJZgC73RMf/dwzejg2COy4QT/E59RPOczgd779rxiRmphMoR8xJYBFRlkTVmcUO4NcUE50Cc39hXezcekHuV1YQK4BXTrxGX1ceiCXYlKAWS9wHZpog9OldTCPBpw5XAWExh3kRzqdvsdHxHVE+TpAEIjDljAlc3r+FPHYH1zWWk41eQ/zz3Vkx5Zl4dMF9x+uUOspQXVb/4K42e9fMKychNUN5o/JzIwy7xOzgXa6iwf223On/mXKV6FK6Q8lojK7Wc8g7AwfqnN9//HjI14pVqGBJtn5ggL/g4qt0JFl3pV/6n/ZLMG6k8wpsaApLGvsTPqZHcv+C69Z33rZQ4TagXVxpmnWMpPCaR0+Dawn4iAce2UvUtIN2KbJNcTtRQo4z30+BbgmVKHgkR0EHMu4cYjJPYwJ5H8IYcQuFKb7+Cp33FD2Lv54I9uvtVHH9bWcid9K82y68PufJi/0icZ3EyEqZygez9mgJzxXO1b7xZMiosGs82QRv7IIOSzqBPRYv1Lxi3fWkgnOvw4dWFxJnKEI2+KD9K0z+XsgVlm26fdRklQAAf6xOJ1nJXBScbm12FBTWLMjLzHWz/iI9mQ+eGV9AREqrgQjUayXdnCsa0Q9bTTktxBkrJND4NUEDSGklhj9SY+VM0mhgAbkCvSE59vKtcNmCHx2Y+JnbZyKzJ71EaErX9vOpYCneKOjn8phVBJHQHM16QRLGyW4DUfn2CtAvb7Kks56kf/mn9YZDU68zSoLzm9rz7fjS2OUsxwmuv2IRCv/UTGgtfEfCs34qzagADfTNKTou7qkedhoygvuHiN4PzgGnjw1DQMks9PWr44z1gvIV4pEGiqgIuNHDjxKsfgQy0Cp2AV1+FNLWd1zd5t/K2pXR+knDoeHIZ2m6txQMl9I4GIyQ1bQFJWrYXPS8oMjvoH0YYVsHyShBsU2SKlG7nGbuUyoCR1EtRIzHMgP1Dq+Whqdbv67pRvhGVmydkCh0wbD+LJBcp2KJK+EQT9vv6GT5JW0oVHnE5TEXCnEJOW/rMhNMTMSccRmnVdguIE4HZsXx+cmV36jHgEt9bzcsvyWvFFoG4xL+t2UUnztX870vu//XaeVuOEAgehY/KLncrY7lhsQA4puCFIWpPteiCNhU1D8DTKc8V0ZtLT9a31SL1NLhZ+YHiD8Hs5SYdj6FW50E5yYUqPRPkg5mpbh88cRcPdsngCxU8iusNN3MSP07lO0h8zULDqtQsAq9p5o7IFTvWlAjekMy1sKTj3CuH7FuAkMHvwU0odMFeaS9T+8+4OGeprHwogWTzTbPnoOqOP/RC6vGfBvpju5s264hYguT24iXzhDFYk/8JQQe+USIbkQ7wXRw+/9cK8h5cs4LyaxMOx0pXHooxJ01bF8BYgYG4s0RB2gItzMk/L5/XhrOdWxEAdYR27s0dCN58gyvoU6phgQbTqvNTFYAObRcjfKfHu3PrFCYBBAKJ7Nm58C3rz832+ZTGVdQ3490TvO+sCLYKzpgtsqr8KyedG9LKa8wn/wlRD7kYn+J2SrMPY2Q0e4evyJaCAsolp/BQfy9JFtyRDPWTHn+jOHjW8ZN7vswGkRwYlSJSl0UC8mmJyS4lwnO/Vv4wBnDHQEzIycjn3JZAlV5ing0HKqUfW6G07453JXd8oZiMC/kIQjgWkdg34zxBYarVVrHFG5FIH9w7QWY8PCDU/kkcLniT0yD1/gkqAG2HpwaXEcSqX8Ofrbpd/IA7R7iCXYE5Q1mAvSvICpPg9Cf3CHjLyAEDz9cwKnZHkocXC8evdsTf2e7Wz8FFPAI3onFvym0MfZuRrIZitX1V8NOLedd3y74CwuErfzrr60DjyPRxGbJ4llMbm+ojeENe0HBedNm71jf+McSihKbSo5GDBxfVYVreYZ8A4iP0LsxtzQFxuzdeDL5KA9uNNw+LN9FN9vKhdALhQSnSfLPfMBsM/ey7dbxb4eRT0fpApX`
+ // EncryptedPrivateKey with "password"
+ EncryptedPrivateKey string = `sPhQsHpXYFqPb7qdmTY7APFwBb4m7meCITujDeKMQFnIjplOVm9ijjXU+YAmGvrX13ukBj8zo9MTVhjJUjJ917pyLhl4w8uyg1jCvplUYtJVXhGA9Wy3NqHMuq3SU3fKdlEM+oR4zYkbAYWp42XvulbcuVBEWiWkvHOrbdKPFpMmd54SL2c/vcWrmjgC7rTlJf2TYICZwRK+6Y0XZi5fSWeU0vg7+rHWKHc5MHHtAdAiL+HCa90c5gfh+hXkT5ojGHOkhT9kdLy3PTPN19EGpdXgZ3WFq1z9CZ6zX7uM091uR0IvgzfwaLx8HJCx7ViWQhioH9LJZgC73RMf/dwzejg2COy4QT/E59RPOczgd779rxiRmphMoR8xJYBFRlkTVmcUO4NcUE50Cc39hXezcekHuV1YQK4BXTrxGX1ceiCXYlKAWS9wHZpog9OldTCPBpw5XAWExh3kRzqdvsdHxHVE+TpAEIjDljAlc3r+FPHYH1zWWk41eQ/zz3Vkx5Zl4dMF9x+uUOspQXVb/4K42e9fMKychNUN5o/JzIwy7xOzgXa6iwf223On/mXKV6FK6Q8lojK7Wc8g7AwfqnN9//HjI14pVqGBJtn5ggL/g4qt0JFl3pV/6n/ZLMG6k8wpsaApLGvsTPqZHcv+C69Z33rZQ4TagXVxpmnWMpPCaR0+Dawn4iAce2UvUtIN2KbJNcTtRQo4z30+BbgmVKHgkR0EHMu4cYjJPYwJ5H8IYcQuFKb7+Cp33FD2Lv54I9uvtVHH9bWcid9K82y68PufJi/0icZ3EyEqZygez9mgJzxXO1b7xZMiosGs82QRv7IIOSzqBPRYv1Lxi3fWkgnOvw4dWFxJnKEI2+KD9K0z+XsgVlm26fdRklQAAf6xOJ1nJXBScbm12FBTWLMjLzHWz/iI9mQ+eGV9AREqrgQjUayXdnCsa0Q9bTTktxBkrJND4NUEDSGklhj9SY+VM0mhgAbkCvSE59vKtcNmCHx2Y+JnbZyKzJ71EaErX9vOpYCneKOjn8phVBJHQHM16QRLGyW4DUfn2CtAvb7Kks56kf/mn9YZDU68zSoLzm9rz7fjS2OUsxwmuv2IRCv/UTGgtfEfCs34qzagADfTNKTou7qkedhoygvuHiN4PzgGnjw1DQMks9PWr44z1gvIV4pEGiqgIuNHDjxKsfgQy0Cp2AV1+FNLWd1zd5t/K2pXR+knDoeHIZ2m6txQMl9I4GIyQ1bQFJWrYXPS8oMjvoH0YYVsHyShBsU2SKlG7nGbuUyoCR1EtRIzHMgP1Dq+Whqdbv67pRvhGVmydkCh0wbD+LJBcp2KJK+EQT9vv6GT5JW0oVHnE5TEXCnEJOW/rMhNMTMSccRmnVdguIE4HZsXx+cmV36jHgEt9bzcsvyWvFFoG4xL+t2UUnztX870vu//XaeVuOEAgehY/KLncrY7lhsQA4puCFIWpPteiCNhU1D8DTKc8V0ZtLT9a31SL1NLhZ+YHiD8Hs5SYdj6FW50E5yYUqPRPkg5mpbh88cRcPdsngCxU8iusNN3MSP07lO0h8zULDqtQsAq9p5o7IFTvWlAjekMy1sKTj3CuH7FuAkMHvwU0odMFeaS9T+8+4OGeprHwogWTzTbPnoOqOP/RC6vGfBvpju5s264hYguT24iXzhDFYk/8JQQe+USIbkQ7wXRw+/9cK8h5cs4LyaxMOx0pXHooxJ01bF8BYgYG4s0RB2gItzMk/L5/XhrOdWxEAdYR27s0dCN58gyvoU6phgQbTqvNTFYAObRcjfKfHu3PrFCYBBAKJ7Nm58C3rz832+ZTGVdQ3490TvO+sCLYKzpgtsqr8KyedG9LKa8wn/wlRD7kYn+J2SrMPY2Q0e4evyJaCAsolp/BQfy9JFtyRDPWTHn+jOHjW8ZN7vswGkRwYlSJSl0UC8mmJyS4lwnO/Vv4wBnDHQEzIycjn3JZAlV5ing0HKqUfW6G07453JXd8oZiMC/kIQjgWkdg34zxBYarVVrHFG5FIH9w7QWY8PCDU/kkcLniT0yD1/gkqAG2HpwaXEcSqX8Ofrbpd/IA7R7iCXYE5Q1mAvSvICpPg9Cf3CHjLyAEDz9cwKnZHkocXC8evdsTf2e7Wz8FFPAI3onFvym0MfZuRrIZitX1V8NOLedd3y74CwuErfzrr60DjyPRxGbJ4llMbm+ojeENe0HBedNm71jf+McSihKbSo5GDBxfVYVreYZ8A4iP0LsxtzQFxuzdeDL5KA9uNNw+LN9FN9vKhdALhQSnSfLPfMBsM/ey7dbxb4eRT0fpApX`
- // Private key for testing server side
- privateKey string = `-----BEGIN PRIVATE KEY-----
+ // PrivateKey for testing server side
+ PrivateKey string = `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJScQQJxWxKwqf
FmXH64QnRBVyW7cU25F+O9Zy96dqTjbV4ruWrzb4+txmK20ZPQvMxDLefhEzTXWb
HZV1P/XxgmEpaBVHwHnkhaPzzChOa/G18CDoCNrgyVzh5a31OotTCuGlS1bSkR53
@@ -42,7 +42,8 @@ b0XvaLzh1iKG7HZ9tvPt/VhHlKKosNBK/j4fvgMZg7/bhRfHmaDQKoqlGbtyWjEQ
mj1b2/Gnbk3VYDR16BFfj7m2
-----END PRIVATE KEY-----`
- publicKey string = `-----BEGIN PUBLIC KEY-----
+ // PublicKey for encryption
+ PublicKey string = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyUnEECcVsSsKnxZlx+uE
J0QVclu3FNuRfjvWcvenak421eK7lq82+PrcZittGT0LzMQy3n4RM011mx2VdT/1
8YJhKWgVR8B55IWj88woTmvxtfAg6Aja4Mlc4eWt9TqLUwrhpUtW0pEedxMT10Kv
@@ -58,35 +59,57 @@ var (
decodedPrivateKey *rsa.PrivateKey
)
-// Seed seeds semi random data for use in testing & development
-func Seed() {
+// GetPubKey for seeding & tests
+func GetPubKey() *rsa.PublicKey {
var (
- block *pem.Block
- decKey any
- ok bool
- err error
+ block *pem.Block
+ decKey any
+ decPubKey *rsa.PublicKey
+ ok bool
+ err error
)
-
- block, _ = pem.Decode([]byte(publicKey))
+ block, _ = pem.Decode([]byte(PublicKey))
decKey, err = x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
- decodedPublicKey, ok = decKey.(*rsa.PublicKey)
+
+ decPubKey, ok = decKey.(*rsa.PublicKey)
if !ok {
panic(errors.New("Invalid decodedPublicKey"))
}
- block, _ = pem.Decode([]byte(privateKey))
+ return decPubKey
+}
+
+// GetPrivKey for seeding & tests
+func GetPrivKey() *rsa.PrivateKey {
+ var (
+ block *pem.Block
+ decKey any
+ decPrivKey *rsa.PrivateKey
+ ok bool
+ err error
+ )
+ block, _ = pem.Decode([]byte(PrivateKey))
decKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
- decodedPrivateKey, ok = decKey.(*rsa.PrivateKey)
+ decPrivKey, ok = decKey.(*rsa.PrivateKey)
if !ok {
panic(errors.New("Invalid decodedPrivateKey"))
}
+ return decPrivKey
+}
+
+// Seed seeds semi random data for use in testing & development
+func Seed() {
+
+ decodedPublicKey = GetPubKey()
+ decodedPrivateKey = GetPrivKey()
+
log.Println("Seeding users...")
SeedUsers()
diff --git a/Backend/Database/Seeder/UserSeeder.go b/Backend/Database/Seeder/UserSeeder.go
index c65a94e..eae651f 100644
--- a/Backend/Database/Seeder/UserSeeder.go
+++ b/Backend/Database/Seeder/UserSeeder.go
@@ -3,9 +3,9 @@ package Seeder
import (
"encoding/base64"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api/Auth"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
)
var userNames = []string{
@@ -25,12 +25,12 @@ var userNames = []string{
func createUser(username string) (Models.User, error) {
var (
userData Models.User
- userKey aesKey
+ userKey AesKey
password string
err error
)
- userKey, err = generateAesKey()
+ userKey, err = GenerateAesKey()
if err != nil {
panic(err)
}
@@ -43,10 +43,10 @@ func createUser(username string) (Models.User, error) {
userData = Models.User{
Username: username,
Password: password,
- AsymmetricPrivateKey: encryptedPrivateKey,
- AsymmetricPublicKey: publicKey,
+ AsymmetricPrivateKey: EncryptedPrivateKey,
+ AsymmetricPublicKey: PublicKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
- encryptWithPublicKey(userKey.Key, decodedPublicKey),
+ EncryptWithPublicKey(userKey.Key, decodedPublicKey),
),
}
diff --git a/Backend/Database/Seeder/encryption.go b/Backend/Database/Seeder/encryption.go
index a116134..16afc11 100644
--- a/Backend/Database/Seeder/encryption.go
+++ b/Backend/Database/Seeder/encryption.go
@@ -17,12 +17,12 @@ import (
"golang.org/x/crypto/pbkdf2"
)
-type aesKey struct {
+type AesKey struct {
Key []byte
Iv []byte
}
-func (key aesKey) encode() string {
+func (key AesKey) encode() string {
return base64.StdEncoding.EncodeToString(key.Key)
}
@@ -71,7 +71,7 @@ func pkcs7strip(data []byte, blockSize int) ([]byte, error) {
return data[:length-padLen], nil
}
-func generateAesKey() (aesKey, error) {
+func GenerateAesKey() (AesKey, error) {
var (
saltBytes []byte = []byte{}
password []byte
@@ -83,22 +83,22 @@ func generateAesKey() (aesKey, error) {
password = make([]byte, 64)
_, err = rand.Read(password)
if err != nil {
- return aesKey{}, err
+ return AesKey{}, err
}
seed = make([]byte, 64)
_, err = rand.Read(seed)
if err != nil {
- return aesKey{}, err
+ return AesKey{}, err
}
iv = make([]byte, 16)
_, err = rand.Read(iv)
if err != nil {
- return aesKey{}, err
+ return AesKey{}, err
}
- return aesKey{
+ return AesKey{
Key: pbkdf2.Key(
password,
saltBytes,
@@ -110,7 +110,7 @@ func generateAesKey() (aesKey, error) {
}, nil
}
-func (key aesKey) aesEncrypt(plaintext []byte) ([]byte, error) {
+func (key AesKey) AesEncrypt(plaintext []byte) ([]byte, error) {
var (
bPlaintext []byte
ciphertext []byte
@@ -134,7 +134,7 @@ func (key aesKey) aesEncrypt(plaintext []byte) ([]byte, error) {
return ciphertext, nil
}
-func (key aesKey) aesDecrypt(ciphertext []byte) ([]byte, error) {
+func (key AesKey) AesDecrypt(ciphertext []byte) ([]byte, error) {
var (
plaintext []byte
iv []byte
@@ -153,11 +153,16 @@ func (key aesKey) aesDecrypt(ciphertext []byte) ([]byte, error) {
decMode := cipher.NewCBCDecrypter(block, iv)
decMode.CryptBlocks(plaintext, plaintext)
+ plaintext, err = pkcs7strip(plaintext, 16)
+ if err != nil {
+ return []byte{}, err
+ }
+
return plaintext, nil
}
// EncryptWithPublicKey encrypts data with public key
-func encryptWithPublicKey(msg []byte, pub *rsa.PublicKey) []byte {
+func EncryptWithPublicKey(msg []byte, pub *rsa.PublicKey) []byte {
var (
hash hash.Hash
)
diff --git a/Backend/Database/Sessions.go b/Backend/Database/Sessions.go
index 1f125df..afee878 100644
--- a/Backend/Database/Sessions.go
+++ b/Backend/Database/Sessions.go
@@ -1,12 +1,13 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm/clause"
)
-func GetSessionById(id string) (Models.Session, error) {
+// GetSessionByID Gets session
+func GetSessionByID(id string) (Models.Session, error) {
var (
session Models.Session
err error
@@ -19,6 +20,7 @@ func GetSessionById(id string) (Models.Session, error) {
return session, err
}
+// CreateSession creates session
func CreateSession(session *Models.Session) error {
var (
err error
@@ -29,10 +31,16 @@ func CreateSession(session *Models.Session) error {
return err
}
+// DeleteSession deletes session
func DeleteSession(session *Models.Session) error {
return DB.Delete(session).Error
}
-func DeleteSessionById(id string) error {
- return DB.Delete(&Models.Session{}, id).Error
+// DeleteSessionByID deletes session
+func DeleteSessionByID(id string) error {
+ return DB.Delete(
+ &Models.Session{},
+ "id = ?",
+ id,
+ ).Error
}
diff --git a/Backend/Database/UserConversations.go b/Backend/Database/UserConversations.go
index 930a98f..cc876c7 100644
--- a/Backend/Database/UserConversations.go
+++ b/Backend/Database/UserConversations.go
@@ -1,7 +1,7 @@
package Database
import (
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -19,13 +19,19 @@ func GetUserConversationById(id string) (Models.UserConversation, error) {
return message, err
}
-func GetUserConversationsByUserId(id string) ([]Models.UserConversation, error) {
+func GetUserConversationsByUserId(id string, page int) ([]Models.UserConversation, error) {
var (
conversations []Models.UserConversation
+ offset int
err error
)
- err = DB.Find(&conversations, "user_id = ?", id).
+ offset = page * PageSize
+
+ err = DB.Offset(offset).
+ Limit(PageSize).
+ Order("created_at DESC").
+ Find(&conversations, "user_id = ?", id).
Error
return conversations, err
diff --git a/Backend/Database/Users.go b/Backend/Database/Users.go
index 2df6a73..c27ba2c 100644
--- a/Backend/Database/Users.go
+++ b/Backend/Database/Users.go
@@ -3,7 +3,7 @@ package Database
import (
"errors"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
diff --git a/Backend/Dockerfile b/Backend/Dockerfile
new file mode 100644
index 0000000..9fea42e
--- /dev/null
+++ b/Backend/Dockerfile
@@ -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" ]
diff --git a/Backend/Models/Conversations.go b/Backend/Models/Conversations.go
index 1c9e53a..6df37ec 100644
--- a/Backend/Models/Conversations.go
+++ b/Backend/Models/Conversations.go
@@ -1,6 +1,8 @@
package Models
import (
+ "time"
+
"github.com/gofrs/uuid"
)
@@ -34,4 +36,5 @@ type UserConversation struct {
ConversationDetailID string `gorm:"not null" json:"conversation_detail_id"` // Stored encrypted
Admin string `gorm:"not null" json:"admin"` // Bool if user is admin of thread, stored encrypted
SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted
+ CreatedAt time.Time `gorm:"not null" json:"created_at"`
}
diff --git a/Backend/Models/Friends.go b/Backend/Models/Friends.go
index 9dc892d..6438d97 100644
--- a/Backend/Models/Friends.go
+++ b/Backend/Models/Friends.go
@@ -2,6 +2,7 @@ package Models
import (
"database/sql"
+ "time"
"github.com/gofrs/uuid"
)
@@ -17,4 +18,5 @@ type FriendRequest struct {
FriendPublicAsymmetricKey string ` json:"asymmetric_public_key"` // Stored encrypted
SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted
AcceptedAt sql.NullTime ` json:"accepted_at"`
+ CreatedAt time.Time `gorm:"not null" json:"created_at"`
}
diff --git a/Backend/Models/Messages.go b/Backend/Models/Messages.go
index bf05e3b..eafac22 100644
--- a/Backend/Models/Messages.go
+++ b/Backend/Models/Messages.go
@@ -25,6 +25,7 @@ type Message struct {
MessageData MessageData ` json:"message_data"`
SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted
AssociationKey string `gorm:"not null" json:"association_key"` // Stored encrypted
- Expiry sql.NullTime ` json:"expiry"`
+ ExpiryRaw string ` json:"expiry"`
+ Expiry sql.NullTime ` json:"-"`
CreatedAt time.Time `gorm:"not null" json:"created_at"`
}
diff --git a/Backend/Models/Users.go b/Backend/Models/Users.go
index 811c3ab..736289e 100644
--- a/Backend/Models/Users.go
+++ b/Backend/Models/Users.go
@@ -2,6 +2,7 @@ package Models
import (
"database/sql/driver"
+ "errors"
"github.com/gofrs/uuid"
"gorm.io/gorm"
@@ -40,10 +41,35 @@ const (
MessageExpiryNoExpiry = "no_expiry"
)
+// MessageExpiryValues list of all expiry values for validation
+var MessageExpiryValues = []string{
+ MessageExpiryFifteenMin,
+ MessageExpiryThirtyMin,
+ MessageExpiryOneHour,
+ MessageExpiryThreeHour,
+ MessageExpirySixHour,
+ MessageExpiryTwelveHour,
+ MessageExpiryOneDay,
+ MessageExpiryThreeDay,
+ MessageExpiryNoExpiry,
+}
+
// Scan new value into MessageExpiry
func (e *MessageExpiry) Scan(value interface{}) error {
- *e = MessageExpiry(value.(string))
- return nil
+ var (
+ strValue = value.(string)
+ m string
+ )
+
+ for _, m = range MessageExpiryValues {
+ if strValue != m {
+ continue
+ }
+ *e = MessageExpiry(strValue)
+ return nil
+ }
+
+ return errors.New("Invalid MessageExpiry value")
}
// Value gets value out of MessageExpiry column
@@ -51,6 +77,10 @@ func (e MessageExpiry) Value() (driver.Value, error) {
return string(e), nil
}
+func (e MessageExpiry) String() string {
+ return string(e)
+}
+
// User holds user data
type User struct {
Base
diff --git a/Backend/Tests/Init.go b/Backend/Tests/Init.go
new file mode 100644
index 0000000..dde5c4f
--- /dev/null
+++ b/Backend/Tests/Init.go
@@ -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
+}
diff --git a/Backend/Util/Files.go b/Backend/Util/Files.go
index 4ee8b81..154b1ef 100644
--- a/Backend/Util/Files.go
+++ b/Backend/Util/Files.go
@@ -10,21 +10,14 @@ func WriteFile(contents []byte) (string, error) {
var (
fileName string
filePath string
- cwd string
f *os.File
err error
)
- cwd, err = os.Getwd()
- if err != nil {
- return fileName, err
- }
-
fileName = RandomString(32)
filePath = fmt.Sprintf(
- "%s/attachments/%s",
- cwd,
+ "/app/attachments/%s",
fileName,
)
diff --git a/Backend/Util/Strings.go b/Backend/Util/Strings.go
index a2d5d0f..879ca23 100644
--- a/Backend/Util/Strings.go
+++ b/Backend/Util/Strings.go
@@ -2,12 +2,18 @@ package Util
import (
"math/rand"
+ "time"
)
var (
letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
)
+func init() {
+ rand.Seed(time.Now().UnixNano())
+}
+
+// RandomString generates a random string
func RandomString(n int) string {
var (
b []rune
diff --git a/Backend/Util/UserHelper.go b/Backend/Util/UserHelper.go
index 32616a6..47b2569 100644
--- a/Backend/Util/UserHelper.go
+++ b/Backend/Util/UserHelper.go
@@ -5,8 +5,8 @@ import (
"log"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Models"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
diff --git a/Backend/go.mod b/Backend/go.mod
index 127bb75..9db656c 100644
--- a/Backend/go.mod
+++ b/Backend/go.mod
@@ -1,9 +1,8 @@
-module git.tovijaeschke.xyz/tovi/Envelope/Backend
+module git.tovijaeschke.xyz/tovi/Capsule/Backend
go 1.18
require (
- github.com/Kangaroux/go-map-schema v0.6.1
github.com/gofrs/uuid v4.2.0+incompatible
github.com/gorilla/mux v1.8.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
diff --git a/Backend/main.go b/Backend/main.go
index e9dc701..8001402 100644
--- a/Backend/main.go
+++ b/Backend/main.go
@@ -5,9 +5,9 @@ import (
"log"
"net/http"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Api"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database"
- "git.tovijaeschke.xyz/tovi/Envelope/Backend/Database/Seeder"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
+ "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"github.com/gorilla/mux"
)
diff --git a/README.md b/README.md
index d52d837..d43ef78 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Envelope
+# Capsule
Encrypted messaging app
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..6c89730
--- /dev/null
+++ b/docker-compose.yml
@@ -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
+
+
diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml
index c3bfaaa..26cb9e0 100644
--- a/mobile/android/app/src/main/AndroidManifest.xml
+++ b/mobile/android/app/src/main/AndroidManifest.xml
@@ -2,7 +2,7 @@
package="com.example.mobile">
deleteDb() async {
- final path = join(await getDatabasesPath(), 'envelope.db');
+ final path = join(await getDatabasesPath(), 'capsule.db');
deleteDatabase(path);
}
Future getDatabaseConnection() async {
WidgetsFlutterBinding.ensureInitialized();
- final path = join(await getDatabasesPath(), 'envelope.db');
+ final path = join(await getDatabasesPath(), 'capsule.db');
final database = openDatabase(
path,
diff --git a/mobile/lib/utils/storage/messages.dart b/mobile/lib/utils/storage/messages.dart
index fd7ced7..8c07669 100644
--- a/mobile/lib/utils/storage/messages.dart
+++ b/mobile/lib/utils/storage/messages.dart
@@ -1,8 +1,8 @@
import 'dart:convert';
import 'dart:io';
-import 'package:Envelope/models/messages.dart';
-import 'package:Envelope/utils/storage/write_file.dart';
+import 'package:Capsule/models/messages.dart';
+import 'package:Capsule/utils/storage/write_file.dart';
import 'package:http/http.dart' as http;
import 'package:sqflite/sqflite.dart';
import 'package:uuid/uuid.dart';
diff --git a/mobile/lib/views/authentication/login.dart b/mobile/lib/views/authentication/login.dart
index 6dce978..d4c56a0 100644
--- a/mobile/lib/views/authentication/login.dart
+++ b/mobile/lib/views/authentication/login.dart
@@ -177,7 +177,7 @@ class _LoginWidgetState extends State {
}).catchError((error) {
print(error);
showMessage(
- 'Could not login to Envelope, please try again later.',
+ 'Could not login to Capsule, please try again later.',
context,
);
});
diff --git a/mobile/lib/views/authentication/signup.dart b/mobile/lib/views/authentication/signup.dart
index 2a190e0..22ac9ab 100644
--- a/mobile/lib/views/authentication/signup.dart
+++ b/mobile/lib/views/authentication/signup.dart
@@ -1,8 +1,8 @@
import 'dart:convert';
import 'dart:typed_data';
-import 'package:Envelope/components/flash_message.dart';
-import 'package:Envelope/models/my_profile.dart';
+import 'package:Capsule/components/flash_message.dart';
+import 'package:Capsule/models/my_profile.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
@@ -176,7 +176,7 @@ class _SignupWidgetState extends State {
.then((dynamic) {
Navigator.of(context).popUntil((route) => route.isFirst);
}).catchError((error) {
- showMessage('Failed to signup to Envelope, please try again later', context);
+ showMessage('Failed to signup to Capsule, please try again later', context);
});
},
child: const Text('Submit'),
diff --git a/mobile/lib/views/authentication/unauthenticated_landing.dart b/mobile/lib/views/authentication/unauthenticated_landing.dart
index 6bcd086..3a7e432 100644
--- a/mobile/lib/views/authentication/unauthenticated_landing.dart
+++ b/mobile/lib/views/authentication/unauthenticated_landing.dart
@@ -46,7 +46,7 @@ class _UnauthenticatedLandingWidgetState extends State