Browse Source

Update tests

pull/4/head
Tovi Jaeschke-Rogers 2 years ago
parent
commit
2a368acc44
21 changed files with 711 additions and 557 deletions
  1. +3
    -67
      Backend/Api/Auth/AddProfileImage_test.go
  2. +5
    -128
      Backend/Api/Auth/ChangeMessageExpiry_test.go
  3. +5
    -183
      Backend/Api/Auth/ChangePassword_test.go
  4. +9
    -54
      Backend/Api/Auth/Login_test.go
  5. +5
    -85
      Backend/Api/Auth/Logout_test.go
  6. +2
    -2
      Backend/Api/Friends/EncryptedFriendsList.go
  7. +15
    -4
      Backend/Api/Messages/Conversations.go
  8. +255
    -0
      Backend/Api/Messages/Conversations_test.go
  9. +1
    -1
      Backend/Api/Messages/CreateConversation.go
  10. +129
    -0
      Backend/Api/Messages/CreateConversation_test.go
  11. +18
    -1
      Backend/Api/Messages/CreateMessage.go
  12. +131
    -0
      Backend/Api/Messages/CreateMessage_test.go
  13. +3
    -3
      Backend/Api/Routes.go
  14. +24
    -24
      Backend/Database/Init.go
  15. +5
    -0
      Backend/Database/Seeder/encryption.go
  16. +8
    -2
      Backend/Database/UserConversations.go
  17. +3
    -0
      Backend/Models/Conversations.go
  18. +2
    -1
      Backend/Models/Messages.go
  19. +87
    -0
      Backend/Tests/Init.go
  20. +0
    -1
      Backend/go.mod
  21. +1
    -1
      test.sh

+ 3
- 67
Backend/Api/Auth/AddProfileImage_test.go View File

@ -4,84 +4,24 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"io/ioutil"
"log"
"net/http" "net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"os" "os"
"testing" "testing"
"time"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
) )
func Test_AddProfileImage(t *testing.T) { func Test_AddProfileImage(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
key, err := Seeder.GenerateAesKey() key, err := Seeder.GenerateAesKey()
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -110,10 +50,6 @@ func Test_AddProfileImage(t *testing.T) {
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/image", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/image", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -125,7 +61,7 @@ func Test_AddProfileImage(t *testing.T) {
return return
} }
u, err = Database.GetUserById(u.ID.String())
u, err := Database.GetUserByUsername("test")
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return


+ 5
- 128
Backend/Api/Auth/ChangeMessageExpiry_test.go View File

@ -2,85 +2,22 @@ package Auth_test
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"io/ioutil"
"log"
"net/http" "net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"testing" "testing"
"time"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
) )
func Test_ChangeMessageExpiry(t *testing.T) { func Test_ChangeMessageExpiry(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
d := struct { d := struct {
MessageExpiry string `json:"message_expiry"` MessageExpiry string `json:"message_expiry"`
}{ }{
@ -91,10 +28,6 @@ func Test_ChangeMessageExpiry(t *testing.T) {
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -105,7 +38,7 @@ func Test_ChangeMessageExpiry(t *testing.T) {
t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode) t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode)
} }
u, err = Database.GetUserById(u.ID.String())
u, err := Database.GetUserByUsername("test")
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
@ -117,65 +50,13 @@ func Test_ChangeMessageExpiry(t *testing.T) {
} }
func Test_ChangeMessageExpiryInvalidData(t *testing.T) { func Test_ChangeMessageExpiryInvalidData(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
d := struct { d := struct {
MessageExpiry string `json:"message_expiry"` MessageExpiry string `json:"message_expiry"`
}{ }{
@ -186,10 +67,6 @@ func Test_ChangeMessageExpiryInvalidData(t *testing.T) {
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message_expiry", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -200,7 +77,7 @@ func Test_ChangeMessageExpiryInvalidData(t *testing.T) {
t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode) t.Errorf("Expected %d, recieved %d", http.StatusUnprocessableEntity, resp.StatusCode)
} }
u, err = Database.GetUserById(u.ID.String())
u, err := Database.GetUserByUsername("test")
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return


+ 5
- 183
Backend/Api/Auth/ChangePassword_test.go View File

@ -2,85 +2,23 @@ package Auth_test
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"io/ioutil"
"log"
"net/http" "net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"testing" "testing"
"time"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
) )
func Test_ChangePassword(t *testing.T) { func Test_ChangePassword(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
d := struct { d := struct {
OldPassword string `json:"old_password"` OldPassword string `json:"old_password"`
NewPassword string `json:"new_password"` NewPassword string `json:"new_password"`
@ -97,10 +35,6 @@ func Test_ChangePassword(t *testing.T) {
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -112,7 +46,7 @@ func Test_ChangePassword(t *testing.T) {
return return
} }
u, err = Database.GetUserById(u.ID.String())
u, err := Database.GetUserByUsername("test")
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
@ -124,65 +58,13 @@ func Test_ChangePassword(t *testing.T) {
} }
func Test_ChangePasswordMismatchConfirmFails(t *testing.T) { func Test_ChangePasswordMismatchConfirmFails(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
d := struct { d := struct {
OldPassword string `json:"old_password"` OldPassword string `json:"old_password"`
NewPassword string `json:"new_password"` NewPassword string `json:"new_password"`
@ -199,10 +81,6 @@ func Test_ChangePasswordMismatchConfirmFails(t *testing.T) {
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -215,65 +93,13 @@ func Test_ChangePasswordMismatchConfirmFails(t *testing.T) {
} }
func Test_ChangePasswordInvalidCurrentPasswordFails(t *testing.T) { func Test_ChangePasswordInvalidCurrentPasswordFails(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
d := struct { d := struct {
OldPassword string `json:"old_password"` OldPassword string `json:"old_password"`
NewPassword string `json:"new_password"` NewPassword string `json:"new_password"`
@ -290,10 +116,6 @@ func Test_ChangePasswordInvalidCurrentPasswordFails(t *testing.T) {
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/change_password", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())


+ 9
- 54
Backend/Api/Auth/Login_test.go View File

@ -2,47 +2,18 @@ package Auth_test
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"io/ioutil"
"log"
"net/http" "net/http"
"net/http/httptest"
"testing" "testing"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
) )
func Test_Login(t *testing.T) { func Test_Login(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
_, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
@ -73,6 +44,12 @@ func Test_Login(t *testing.T) {
return return
} }
u, err := Database.GetUserByUsername("test")
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
var session Models.Session var session Models.Session
err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error
@ -84,30 +61,8 @@ func Test_Login(t *testing.T) {
} }
func Test_Login_PasswordFails(t *testing.T) { func Test_Login_PasswordFails(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
_, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return


+ 5
- 85
Backend/Api/Auth/Logout_test.go View File

@ -1,72 +1,26 @@
package Auth_test package Auth_test
import ( import (
"bytes"
"encoding/base64"
"encoding/json"
"io/ioutil"
"log"
"net/http" "net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"testing" "testing"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
) )
func Test_Logout(t *testing.T) { func Test_Logout(t *testing.T) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
client, ts, err := Tests.InitTestEnv()
defer ts.Close() defer ts.Close()
userKey, _ := Seeder.GenerateAesKey()
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err := Database.CreateUser(&u)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
return return
} }
d := struct {
Username string `json:"username"`
Password string `json:"password"`
}{
Username: "test",
Password: "password",
}
jsonStr, _ := json.Marshal(d)
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/login", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
resp, err := client.Get(ts.URL + "/api/v1/logout")
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
t.Errorf("Expected user record, recieved %s", err.Error())
return return
} }
@ -77,46 +31,12 @@ func Test_Logout(t *testing.T) {
var session Models.Session var session Models.Session
err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error
if err != nil {
t.Errorf("Expected session record, recieved %s", err.Error())
return
}
jar, err := cookiejar.New(nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
&http.Cookie{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
client = &http.Client{
Jar: jar,
}
resp, err = client.Get(ts.URL + "/api/v1/logout")
u, err := Database.GetUserByUsername("test")
if err != nil { if err != nil {
t.Errorf("Expected user record, recieved %s", err.Error()) t.Errorf("Expected user record, recieved %s", err.Error())
return return
} }
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error err = Database.DB.First(&session, "user_id = ?", u.ID.String()).Error
if err == nil { if err == nil {
t.Errorf("Expected no session record, recieved %s", session.UserID) t.Errorf("Expected no session record, recieved %s", session.UserID)


+ 2
- 2
Backend/Api/Friends/EncryptedFriendsList.go View File

@ -9,8 +9,8 @@ import (
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
) )
// EncryptedFriendRequestList gets friend request list
func EncryptedFriendRequestList(w http.ResponseWriter, r *http.Request) {
// FriendRequestList gets friend request list
func FriendRequestList(w http.ResponseWriter, r *http.Request) {
var ( var (
userSession Models.Session userSession Models.Session
friends []Models.FriendRequest friends []Models.FriendRequest


+ 15
- 4
Backend/Api/Messages/Conversations.go View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"strings" "strings"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
@ -11,15 +12,24 @@ import (
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" "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 ( var (
conversationDetails []Models.UserConversation conversationDetails []Models.UserConversation
userSession Models.Session userSession Models.Session
returnJSON []byte returnJSON []byte
values url.Values
page int
err error err error
) )
values = r.URL.Query()
page, err = strconv.Atoi(values.Get("page"))
if err != nil {
page = 0
}
userSession, err = Auth.CheckCookie(r) userSession, err = Auth.CheckCookie(r)
if err != nil { if err != nil {
http.Error(w, "Forbidden", http.StatusUnauthorized) http.Error(w, "Forbidden", http.StatusUnauthorized)
@ -28,6 +38,7 @@ func EncryptedConversationList(w http.ResponseWriter, r *http.Request) {
conversationDetails, err = Database.GetUserConversationsByUserId( conversationDetails, err = Database.GetUserConversationsByUserId(
userSession.UserID.String(), userSession.UserID.String(),
page,
) )
if err != nil { if err != nil {
http.Error(w, "Error", http.StatusInternalServerError) http.Error(w, "Error", http.StatusInternalServerError)
@ -44,8 +55,8 @@ func EncryptedConversationList(w http.ResponseWriter, r *http.Request) {
w.Write(returnJSON) 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 ( var (
conversationDetails []Models.ConversationDetail conversationDetails []Models.ConversationDetail
detail Models.ConversationDetail detail Models.ConversationDetail


+ 255
- 0
Backend/Api/Messages/Conversations_test.go View File

@ -0,0 +1,255 @@
package Messages_test
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"testing"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
)
func Test_ConversationsList(t *testing.T) {
client, ts, err := Tests.InitTestEnv()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
u, err := Database.GetUserByUsername("test")
key, err := Seeder.GenerateAesKey()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
nameCiphertext, err := key.AesEncrypt([]byte("Test conversation"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
twoUserCiphertext, err := key.AesEncrypt([]byte("false"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
messageThread := Models.ConversationDetail{
Name: base64.StdEncoding.EncodeToString(nameCiphertext),
TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext),
}
err = Database.CreateConversationDetail(&messageThread)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(messageThread.ID.String()))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
adminCiphertext, err := key.AesEncrypt([]byte("true"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
pubKey := Seeder.GetPubKey()
messageThreadUser := Models.UserConversation{
UserID: u.ID,
ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext),
Admin: base64.StdEncoding.EncodeToString(adminCiphertext),
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(key.Key, pubKey),
),
}
err = Database.CreateUserConversation(&messageThreadUser)
req, _ := http.NewRequest("GET", ts.URL+"/api/v1/auth/conversations", nil)
resp, err := client.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
requestBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
var conversations []Models.UserConversation
json.Unmarshal(requestBody, &conversations)
if len(conversations) != 1 {
t.Errorf("Expected %d, recieved %d", 1, len(conversations))
}
conv := conversations[0]
decodedId, err := base64.StdEncoding.DecodeString(conv.ConversationDetailID)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
decrypedId, err := key.AesDecrypt(decodedId)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
req, _ = http.NewRequest(
"GET",
ts.URL+"/api/v1/auth/conversation_details?conversation_detail_ids="+string(decrypedId),
nil,
)
resp, err = client.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
var conversationDetails []Models.ConversationDetail
requestBody, err = ioutil.ReadAll(resp.Body)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
json.Unmarshal(requestBody, &conversationDetails)
if len(conversationDetails) != 1 {
t.Errorf("Expected %d, recieved %d", 1, len(conversations))
}
decodedName, err := base64.StdEncoding.DecodeString(conversationDetails[0].Name)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
decrypedName, err := key.AesDecrypt(decodedName)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
if string(decrypedName) != "Test conversation" {
t.Errorf("Expected %s, recieved %s", "Test converation", string(decrypedName))
}
}
func Test_ConversationsListPagination(t *testing.T) {
client, ts, err := Tests.InitTestEnv()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
u, err := Database.GetUserByUsername("test")
key, err := Seeder.GenerateAesKey()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
for i := 0; i < 40; i++ {
nameCiphertext, err := key.AesEncrypt([]byte(
fmt.Sprintf("Test conversation %d", i),
))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
twoUserCiphertext, err := key.AesEncrypt([]byte("false"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
messageThread := Models.ConversationDetail{
Name: base64.StdEncoding.EncodeToString(nameCiphertext),
TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext),
}
err = Database.CreateConversationDetail(&messageThread)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(messageThread.ID.String()))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
adminCiphertext, err := key.AesEncrypt([]byte("true"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
pubKey := Seeder.GetPubKey()
messageThreadUser := Models.UserConversation{
UserID: u.ID,
ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext),
Admin: base64.StdEncoding.EncodeToString(adminCiphertext),
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(key.Key, pubKey),
),
}
err = Database.CreateUserConversation(&messageThreadUser)
}
req, _ := http.NewRequest("GET", ts.URL+"/api/v1/auth/conversations?page=0", nil)
resp, err := client.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
requestBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode)
return
}
var conversations []Models.UserConversation
json.Unmarshal(requestBody, &conversations)
if len(conversations) != 20 {
t.Errorf("Expected %d, recieved %d", 1, len(conversations))
}
}

+ 1
- 1
Backend/Api/Messages/CreateConversation.go View File

@ -54,5 +54,5 @@ func CreateConversation(w http.ResponseWriter, r *http.Request) {
return return
} }
w.WriteHeader(http.StatusOK)
w.WriteHeader(http.StatusNoContent)
} }

+ 129
- 0
Backend/Api/Messages/CreateConversation_test.go View File

@ -0,0 +1,129 @@
package Messages_test
import (
"bytes"
"encoding/base64"
"encoding/json"
"net/http"
"testing"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
"github.com/gofrs/uuid"
)
func Test_CreateConversation(t *testing.T) {
client, ts, err := Tests.InitTestEnv()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
u, err := Database.GetUserByUsername("test")
key, err := Seeder.GenerateAesKey()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
nameCiphertext, err := key.AesEncrypt([]byte("Test conversation"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
twoUserCiphertext, err := key.AesEncrypt([]byte("false"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
id, err := uuid.NewV4()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
conversationDetailIDCiphertext, err := key.AesEncrypt([]byte(id.String()))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
adminCiphertext, err := key.AesEncrypt([]byte("true"))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
userIDCiphertext, err := key.AesEncrypt([]byte(u.ID.String()))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
usernameCiphertext, err := key.AesEncrypt([]byte(u.Username))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
pubKey := Seeder.GetPubKey()
d := struct {
ID string `json:"id"`
Name string `json:"name"`
TwoUser string `json:"two_user"`
Users []Models.ConversationDetailUser `json:"users"`
UserConversations []Models.UserConversation `json:"user_conversations"`
}{
ID: id.String(),
Name: base64.StdEncoding.EncodeToString(nameCiphertext),
TwoUser: base64.StdEncoding.EncodeToString(twoUserCiphertext),
Users: []Models.ConversationDetailUser{
{
ConversationDetailID: id,
UserID: base64.StdEncoding.EncodeToString(userIDCiphertext),
Username: base64.StdEncoding.EncodeToString(usernameCiphertext),
AssociationKey: "",
PublicKey: "",
Admin: base64.StdEncoding.EncodeToString(adminCiphertext),
},
},
UserConversations: []Models.UserConversation{
{
UserID: u.ID,
ConversationDetailID: base64.StdEncoding.EncodeToString(conversationDetailIDCiphertext),
Admin: base64.StdEncoding.EncodeToString(adminCiphertext),
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(key.Key, pubKey),
),
},
},
}
jsonStr, _ := json.Marshal(d)
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/conversations", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
if resp.StatusCode != http.StatusNoContent {
t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode)
}
var c Models.ConversationDetail
err = Database.DB.First(&c, "id = ?", id.String()).Error
if err != nil {
t.Errorf("Expected conversation detail record, received %s", err.Error())
return
}
}

+ 18
- 1
Backend/Api/Messages/CreateMessage.go View File

@ -4,6 +4,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"net/http" "net/http"
"time"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
@ -20,8 +21,11 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) {
var ( var (
messagesData []rawMessageData messagesData []rawMessageData
messageData rawMessageData messageData rawMessageData
message Models.Message
t time.Time
decodedFile []byte decodedFile []byte
fileName string fileName string
i int
err error err error
) )
@ -38,6 +42,19 @@ func CreateMessage(w http.ResponseWriter, r *http.Request) {
messageData.MessageData.Attachment.FilePath = fileName 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) err = Database.CreateMessageData(&messageData.MessageData)
if err != nil { if err != nil {
http.Error(w, "Error", http.StatusInternalServerError) 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)
} }

+ 131
- 0
Backend/Api/Messages/CreateMessage_test.go View File

@ -0,0 +1,131 @@
package Messages_test
import (
"bytes"
"encoding/base64"
"encoding/json"
"net/http"
"testing"
"time"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests"
"github.com/gofrs/uuid"
)
func Test_CreateMessage(t *testing.T) {
client, ts, err := Tests.InitTestEnv()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
u, err := Database.GetUserByUsername("test")
key, err := Seeder.GenerateAesKey()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
dataCiphertext, err := key.AesEncrypt([]byte("Test message..."))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
senderIDCiphertext, err := key.AesEncrypt([]byte(u.ID.String()))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
id, err := uuid.NewV4()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
id2, err := uuid.NewV4()
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
d := []struct {
MessageData struct {
ID uuid.UUID `json:"id"`
Data string `json:"data"`
SenderID string `json:"sender_id"`
SymmetricKey string `json:"symmetric_key"`
} `json:"message_data"`
Messages []struct {
ID uuid.UUID `json:"id"`
MessageDataID uuid.UUID `json:"message_data_id"`
SymmetricKey string `json:"symmetric_key"`
AssociationKey string `json:"association_key"`
Expiry time.Time `json:"expiry"`
} `json:"message"`
}{
{
MessageData: struct {
ID uuid.UUID `json:"id"`
Data string `json:"data"`
SenderID string `json:"sender_id"`
SymmetricKey string `json:"symmetric_key"`
}{
ID: id,
Data: base64.StdEncoding.EncodeToString(dataCiphertext),
SenderID: base64.StdEncoding.EncodeToString(senderIDCiphertext),
SymmetricKey: "",
},
Messages: []struct {
ID uuid.UUID `json:"id"`
MessageDataID uuid.UUID `json:"message_data_id"`
SymmetricKey string `json:"symmetric_key"`
AssociationKey string `json:"association_key"`
Expiry time.Time `json:"expiry"`
}{
{
ID: id2,
MessageDataID: id,
SymmetricKey: "",
AssociationKey: "",
Expiry: time.Now(),
},
},
},
}
jsonStr, _ := json.Marshal(d)
req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/message", bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
if resp.StatusCode != http.StatusNoContent {
t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode)
return
}
var m Models.Message
err = Database.DB.First(&m).Error
if err != nil {
t.Errorf("Expected conversation detail record, received %s", err.Error())
return
}
var md Models.MessageData
err = Database.DB.First(&md).Error
if err != nil {
t.Errorf("Expected conversation detail record, received %s", err.Error())
return
}
}

+ 3
- 3
Backend/Api/Routes.go View File

@ -68,14 +68,14 @@ func InitAPIEndpoints(router *mux.Router) {
authAPI.HandleFunc("/users", Users.SearchUsers).Methods("GET") 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", Friends.CreateFriendRequest).Methods("POST")
authAPI.HandleFunc("/friend_request/qr_code", Friends.CreateFriendRequestQrCode).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.AcceptFriendRequest).Methods("POST")
authAPI.HandleFunc("/friend_request/{requestID}", Friends.RejectFriendRequest).Methods("DELETE") 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.CreateConversation).Methods("POST")
authAPI.HandleFunc("/conversations", Messages.UpdateConversation).Methods("PUT") authAPI.HandleFunc("/conversations", Messages.UpdateConversation).Methods("PUT")
authAPI.HandleFunc("/conversations/{detailID}/image", Messages.AddConversationImage).Methods("POST") authAPI.HandleFunc("/conversations/{detailID}/image", Messages.AddConversationImage).Methods("POST")


+ 24
- 24
Backend/Database/Init.go View File

@ -12,30 +12,29 @@ import (
const ( const (
dbURL = "postgres://postgres:password@postgres:5432/capsule" dbURL = "postgres://postgres:password@postgres:5432/capsule"
dbTestURL = "postgres://postgres:password@postgres-testing:5432/capsule-testing" dbTestURL = "postgres://postgres:password@postgres-testing:5432/capsule-testing"
PageSize = 20
) )
// DB db // DB db
var DB *gorm.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 // Init initializes the database connection
func Init() { func Init() {
var ( var (
model interface{}
err error
err error
) )
log.Println("Initializing database...") log.Println("Initializing database...")
@ -48,19 +47,16 @@ func Init() {
log.Println("Running AutoMigrate...") 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 // InitTest initializes the test datbase
func InitTest() { func InitTest() {
var ( var (
model interface{}
err error
err error
) )
DB, err = gorm.Open(postgres.Open(dbTestURL), &gorm.Config{}) DB, err = gorm.Open(postgres.Open(dbTestURL), &gorm.Config{})
@ -69,8 +65,12 @@ func InitTest() {
log.Fatalln(err) 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)
} }
} }

+ 5
- 0
Backend/Database/Seeder/encryption.go View File

@ -153,6 +153,11 @@ func (key aesKey) AesDecrypt(ciphertext []byte) ([]byte, error) {
decMode := cipher.NewCBCDecrypter(block, iv) decMode := cipher.NewCBCDecrypter(block, iv)
decMode.CryptBlocks(plaintext, plaintext) decMode.CryptBlocks(plaintext, plaintext)
plaintext, err = pkcs7strip(plaintext, 16)
if err != nil {
return []byte{}, err
}
return plaintext, nil return plaintext, nil
} }


+ 8
- 2
Backend/Database/UserConversations.go View File

@ -19,13 +19,19 @@ func GetUserConversationById(id string) (Models.UserConversation, error) {
return message, err return message, err
} }
func GetUserConversationsByUserId(id string) ([]Models.UserConversation, error) {
func GetUserConversationsByUserId(id string, page int) ([]Models.UserConversation, error) {
var ( var (
conversations []Models.UserConversation conversations []Models.UserConversation
offset int
err error 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 Error
return conversations, err return conversations, err


+ 3
- 0
Backend/Models/Conversations.go View File

@ -1,6 +1,8 @@
package Models package Models
import ( import (
"time"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
) )
@ -34,4 +36,5 @@ type UserConversation struct {
ConversationDetailID string `gorm:"not null" json:"conversation_detail_id"` // Stored encrypted 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 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 SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted
CreatedAt time.Time `gorm:"not null" json:"created_at"`
} }

+ 2
- 1
Backend/Models/Messages.go View File

@ -25,6 +25,7 @@ type Message struct {
MessageData MessageData ` json:"message_data"` MessageData MessageData ` json:"message_data"`
SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted
AssociationKey string `gorm:"not null" json:"association_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"` CreatedAt time.Time `gorm:"not null" json:"created_at"`
} }

+ 87
- 0
Backend/Tests/Init.go View File

@ -0,0 +1,87 @@
package Tests
import (
"encoding/base64"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"time"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api/Auth"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
// InitTestEnv initializes the test environment
// client is used for making authenticated requests
// ts is the testing server
// err, in case it fails ¯\_(ツ)_/¯
func InitTestEnv() (*http.Client, *httptest.Server, error) {
log.SetOutput(ioutil.Discard)
Database.InitTest()
r := mux.NewRouter()
Api.InitAPIEndpoints(r)
ts := httptest.NewServer(r)
userKey, err := Seeder.GenerateAesKey()
if err != nil {
return http.DefaultClient, ts, err
}
pubKey := Seeder.GetPubKey()
p, _ := Auth.HashPassword("password")
u := Models.User{
Username: "test",
Password: p,
AsymmetricPublicKey: Seeder.PublicKey,
AsymmetricPrivateKey: Seeder.EncryptedPrivateKey,
SymmetricKey: base64.StdEncoding.EncodeToString(
Seeder.EncryptWithPublicKey(userKey.Key, pubKey),
),
}
err = Database.CreateUser(&u)
if err != nil {
return http.DefaultClient, ts, err
}
session := Models.Session{
UserID: u.ID,
Expiry: time.Now().Add(12 * time.Hour),
}
err = Database.CreateSession(&session)
if err != nil {
return http.DefaultClient, ts, err
}
jar, err := cookiejar.New(nil)
url, _ := url.Parse(ts.URL)
jar.SetCookies(
url,
[]*http.Cookie{
{
Name: "session_token",
Value: session.ID.String(),
MaxAge: 300,
},
},
)
client := &http.Client{
Jar: jar,
}
return client, ts, err
}

+ 0
- 1
Backend/go.mod View File

@ -3,7 +3,6 @@ module git.tovijaeschke.xyz/tovi/Capsule/Backend
go 1.18 go 1.18
require ( require (
github.com/Kangaroux/go-map-schema v0.6.1
github.com/gofrs/uuid v4.2.0+incompatible github.com/gofrs/uuid v4.2.0+incompatible
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519


+ 1
- 1
test.sh View File

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
docker-compose exec server sh -c "cd /app && go test -v ./..."
docker-compose exec server sh -c "cd /app && go test -p 1 -v ./..."

Loading…
Cancel
Save