| @ -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 | |||
| } | |||
| } | |||
| @ -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") | |||
| } | |||
| } | |||
| @ -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) | |||
| } | |||
| } | |||
| @ -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 | |||
| } | |||
| @ -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,3 +1,3 @@ | |||
| #!/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 ./..." | |||