Browse Source

Add more tests for Api/Auth routes

pull/4/head
Tovi Jaeschke-Rogers 2 years ago
parent
commit
ee3de6a1a5
16 changed files with 728 additions and 221 deletions
  1. +10
    -0
      Backend/Api/Auth/AddProfileImage.go
  2. +143
    -0
      Backend/Api/Auth/AddProfileImage_test.go
  3. +6
    -2
      Backend/Api/Auth/ChangeMessageExpiry.go
  4. +212
    -0
      Backend/Api/Auth/ChangeMessageExpiry_test.go
  5. +1
    -1
      Backend/Api/Auth/ChangePassword.go
  6. +306
    -0
      Backend/Api/Auth/ChangePassword_test.go
  7. +0
    -6
      Backend/Api/Auth/Logout_test.go
  8. BIN
      Backend/Api/Auth/profile_picture_test.png
  9. +0
    -76
      Backend/Api/JsonSerialization/DeserializeUserJson.go
  10. +0
    -109
      Backend/Api/JsonSerialization/VerifyJson.go
  11. +1
    -1
      Backend/Database/Seeder/FriendSeeder.go
  12. +13
    -13
      Backend/Database/Seeder/MessageSeeder.go
  13. +2
    -2
      Backend/Database/Seeder/encryption.go
  14. +32
    -2
      Backend/Models/Users.go
  15. +1
    -8
      Backend/Util/Files.go
  16. +1
    -1
      test.sh

+ 10
- 0
Backend/Api/Auth/AddProfileImage.go View File

@ -35,7 +35,17 @@ func AddProfileImage(w http.ResponseWriter, r *http.Request) {
} }
decodedFile, err = base64.StdEncoding.DecodeString(attachment.Data) decodedFile, err = base64.StdEncoding.DecodeString(attachment.Data)
if err != nil {
http.Error(w, "Error", http.StatusInternalServerError)
return
}
fileName, err = Util.WriteFile(decodedFile) fileName, err = Util.WriteFile(decodedFile)
if err != nil {
http.Error(w, "Error", http.StatusInternalServerError)
return
}
attachment.FilePath = fileName attachment.FilePath = fileName
user.Attachment = attachment user.Attachment = attachment


+ 143
- 0
Backend/Api/Auth/AddProfileImage_test.go View File

@ -0,0 +1,143 @@
package Auth_test
import (
"bytes"
"encoding/base64"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"os"
"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/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
func Test_AddProfileImage(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()
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 {
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,
},
},
)
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")
client := &http.Client{
Jar: jar,
}
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.GetUserById(u.ID.String())
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
}
}

+ 6
- 2
Backend/Api/Auth/ChangeMessageExpiry.go View File

@ -37,7 +37,11 @@ func ChangeMessageExpiry(w http.ResponseWriter, r *http.Request) {
return 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( err = Database.UpdateUser(
user.ID.String(), user.ID.String(),
@ -48,5 +52,5 @@ func ChangeMessageExpiry(w http.ResponseWriter, r *http.Request) {
return return
} }
w.WriteHeader(http.StatusOK)
w.WriteHeader(http.StatusNoContent)
} }

+ 212
- 0
Backend/Api/Auth/ChangeMessageExpiry_test.go View File

@ -0,0 +1,212 @@
package Auth_test
import (
"bytes"
"encoding/base64"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"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/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
func Test_ChangeMessageExpiry(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()
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 {
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 {
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")
client := &http.Client{
Jar: jar,
}
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.GetUserById(u.ID.String())
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) {
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()
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 {
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 {
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")
client := &http.Client{
Jar: jar,
}
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.GetUserById(u.ID.String())
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")
}
}

+ 1
- 1
Backend/Api/Auth/ChangePassword.go View File

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

+ 306
- 0
Backend/Api/Auth/ChangePassword_test.go View File

@ -0,0 +1,306 @@
package Auth_test
import (
"bytes"
"encoding/base64"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"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/Seeder"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Models"
"github.com/gorilla/mux"
)
func Test_ChangePassword(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()
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 {
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 {
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")
client := &http.Client{
Jar: jar,
}
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.GetUserById(u.ID.String())
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) {
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()
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 {
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 {
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")
client := &http.Client{
Jar: jar,
}
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) {
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()
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 {
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 {
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")
client := &http.Client{
Jar: jar,
}
resp, err := client.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
if resp.StatusCode != http.StatusForbidden {
t.Errorf("Expected %d, recieved %d", http.StatusForbidden, resp.StatusCode)
}
}

+ 0
- 6
Backend/Api/Auth/Logout_test.go View File

@ -10,7 +10,6 @@ import (
"net/http/cookiejar" "net/http/cookiejar"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"sync"
"testing" "testing"
"git.tovijaeschke.xyz/tovi/Capsule/Backend/Api" "git.tovijaeschke.xyz/tovi/Capsule/Backend/Api"
@ -21,11 +20,6 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
type Jar struct {
lk sync.Mutex
cookies map[string][]*http.Cookie
}
func Test_Logout(t *testing.T) { func Test_Logout(t *testing.T) {
log.SetOutput(ioutil.Discard) log.SetOutput(ioutil.Discard)
Database.InitTest() Database.InitTest()


BIN
Backend/Api/Auth/profile_picture_test.png View File

Before After
Width: 487  |  Height: 530  |  Size: 136 KiB

+ 0
- 76
Backend/Api/JsonSerialization/DeserializeUserJson.go View File

@ -1,76 +0,0 @@
package JsonSerialization
import (
"encoding/json"
"errors"
"fmt"
"strings"
"git.tovijaeschke.xyz/tovi/Capsule/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
}

+ 0
- 109
Backend/Api/JsonSerialization/VerifyJson.go View File

@ -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
}

+ 1
- 1
Backend/Database/Seeder/FriendSeeder.go View File

@ -23,7 +23,7 @@ func seedFriend(userRequestTo, userRequestFrom Models.User, accepted bool) error
return err return err
} }
encPublicKey, err = symKey.aesEncrypt([]byte(PublicKey))
encPublicKey, err = symKey.AesEncrypt([]byte(PublicKey))
if err != nil { if err != nil {
return err return err
} }


+ 13
- 13
Backend/Database/Seeder/MessageSeeder.go View File

@ -37,24 +37,24 @@ func seedMessage(
panic(err) panic(err)
} }
dataCiphertext, err = key.aesEncrypt([]byte(plaintext))
dataCiphertext, err = key.AesEncrypt([]byte(plaintext))
if err != nil { if err != nil {
panic(err) panic(err)
} }
senderIDCiphertext, err = key.aesEncrypt([]byte(primaryUser.ID.String()))
senderIDCiphertext, err = key.AesEncrypt([]byte(primaryUser.ID.String()))
if err != nil { if err != nil {
panic(err) panic(err)
} }
if i%2 == 0 { if i%2 == 0 {
senderIDCiphertext, err = key.aesEncrypt([]byte(secondaryUser.ID.String()))
senderIDCiphertext, err = key.AesEncrypt([]byte(secondaryUser.ID.String()))
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
keyCiphertext, err = userKey.aesEncrypt(
keyCiphertext, err = userKey.AesEncrypt(
[]byte(base64.StdEncoding.EncodeToString(key.Key)), []byte(base64.StdEncoding.EncodeToString(key.Key)),
) )
if err != nil { if err != nil {
@ -102,12 +102,12 @@ func seedConversationDetail(key aesKey) (Models.ConversationDetail, error) {
name = "Test Conversation" name = "Test Conversation"
nameCiphertext, err = key.aesEncrypt([]byte(name))
nameCiphertext, err = key.AesEncrypt([]byte(name))
if err != nil { if err != nil {
panic(err) panic(err)
} }
twoUserCiphertext, err = key.aesEncrypt([]byte("false"))
twoUserCiphertext, err = key.AesEncrypt([]byte("false"))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -133,12 +133,12 @@ func seedUserConversation(
err error err error
) )
conversationDetailIDCiphertext, err = key.aesEncrypt([]byte(threadID.String()))
conversationDetailIDCiphertext, err = key.AesEncrypt([]byte(threadID.String()))
if err != nil { if err != nil {
return messageThreadUser, err return messageThreadUser, err
} }
adminCiphertext, err = key.aesEncrypt([]byte("true"))
adminCiphertext, err = key.AesEncrypt([]byte("true"))
if err != nil { if err != nil {
return messageThreadUser, err return messageThreadUser, err
} }
@ -181,27 +181,27 @@ func seedConversationDetailUser(
adminString = "true" adminString = "true"
} }
userIDCiphertext, err = key.aesEncrypt([]byte(user.ID.String()))
userIDCiphertext, err = key.AesEncrypt([]byte(user.ID.String()))
if err != nil { if err != nil {
return conversationDetailUser, err return conversationDetailUser, err
} }
usernameCiphertext, err = key.aesEncrypt([]byte(user.Username))
usernameCiphertext, err = key.AesEncrypt([]byte(user.Username))
if err != nil { if err != nil {
return conversationDetailUser, err return conversationDetailUser, err
} }
adminCiphertext, err = key.aesEncrypt([]byte(adminString))
adminCiphertext, err = key.AesEncrypt([]byte(adminString))
if err != nil { if err != nil {
return conversationDetailUser, err return conversationDetailUser, err
} }
associationKeyCiphertext, err = key.aesEncrypt([]byte(associationKey.String()))
associationKeyCiphertext, err = key.AesEncrypt([]byte(associationKey.String()))
if err != nil { if err != nil {
return conversationDetailUser, err return conversationDetailUser, err
} }
publicKeyCiphertext, err = key.aesEncrypt([]byte(user.AsymmetricPublicKey))
publicKeyCiphertext, err = key.AesEncrypt([]byte(user.AsymmetricPublicKey))
if err != nil { if err != nil {
return conversationDetailUser, err return conversationDetailUser, err
} }


+ 2
- 2
Backend/Database/Seeder/encryption.go View File

@ -110,7 +110,7 @@ func GenerateAesKey() (aesKey, error) {
}, nil }, nil
} }
func (key aesKey) aesEncrypt(plaintext []byte) ([]byte, error) {
func (key aesKey) AesEncrypt(plaintext []byte) ([]byte, error) {
var ( var (
bPlaintext []byte bPlaintext []byte
ciphertext []byte ciphertext []byte
@ -134,7 +134,7 @@ func (key aesKey) aesEncrypt(plaintext []byte) ([]byte, error) {
return ciphertext, nil return ciphertext, nil
} }
func (key aesKey) aesDecrypt(ciphertext []byte) ([]byte, error) {
func (key aesKey) AesDecrypt(ciphertext []byte) ([]byte, error) {
var ( var (
plaintext []byte plaintext []byte
iv []byte iv []byte


+ 32
- 2
Backend/Models/Users.go View File

@ -2,6 +2,7 @@ package Models
import ( import (
"database/sql/driver" "database/sql/driver"
"errors"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"gorm.io/gorm" "gorm.io/gorm"
@ -40,10 +41,35 @@ const (
MessageExpiryNoExpiry = "no_expiry" 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 // Scan new value into MessageExpiry
func (e *MessageExpiry) Scan(value interface{}) error { 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 // Value gets value out of MessageExpiry column
@ -51,6 +77,10 @@ func (e MessageExpiry) Value() (driver.Value, error) {
return string(e), nil return string(e), nil
} }
func (e MessageExpiry) String() string {
return string(e)
}
// User holds user data // User holds user data
type User struct { type User struct {
Base Base


+ 1
- 8
Backend/Util/Files.go View File

@ -10,21 +10,14 @@ func WriteFile(contents []byte) (string, error) {
var ( var (
fileName string fileName string
filePath string filePath string
cwd string
f *os.File f *os.File
err error err error
) )
cwd, err = os.Getwd()
if err != nil {
return fileName, err
}
fileName = RandomString(32) fileName = RandomString(32)
filePath = fmt.Sprintf( filePath = fmt.Sprintf(
"%s/attachments/%s",
cwd,
"/app/attachments/%s",
fileName, fileName,
) )


+ 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 ./Api/Auth"
docker-compose exec server sh -c "cd /app && go test -v ./..."

Loading…
Cancel
Save