Prefix replacement of the old application-nested module path in go.mod and every import. No identifier, string, table, migration ID, config key or comment changes.
120 lines
6.2 KiB
Go
120 lines
6.2 KiB
Go
package user
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.golem15.com/golem15/sm-user-plugin/controllers"
|
|
)
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
app, gdb := sessionApp(t, "0s")
|
|
token := loginToken(t, app, gdb, "ada-update@example.test")
|
|
other := insertUser(t, gdb, "other-update@example.test", "correct-horse")
|
|
_ = other
|
|
body := `{"name":"Ada","surname":"Lovelace","email":"ada-update@example.test"}`
|
|
rec := bearerJSON(t, controllers.Update(app), "/_user/api/v1/update", token, body)
|
|
if rec.Code != http.StatusOK || !strings.Contains(rec.Body.String(), `"message":"Profile updated"`) || !strings.Contains(rec.Body.String(), `"name":"Ada"`) {
|
|
t.Fatalf("update %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
again := bearerJSON(t, controllers.Update(app), "/_user/api/v1/update", token, body)
|
|
if again.Code != http.StatusOK {
|
|
t.Fatalf("own email %d %s", again.Code, again.Body.String())
|
|
}
|
|
dup := bearerJSON(t, controllers.Update(app), "/_user/api/v1/update", token, `{"name":"Ada","surname":"Lovelace","email":"other-update@example.test"}`)
|
|
if dup.Code != http.StatusUnprocessableEntity {
|
|
t.Fatalf("duplicate %d %s", dup.Code, dup.Body.String())
|
|
}
|
|
missing := bearerJSON(t, controllers.Update(app), "/_user/api/v1/update", token, `{"surname":"Lovelace","email":"ada-update@example.test"}`)
|
|
if missing.Code != http.StatusUnprocessableEntity {
|
|
t.Fatalf("missing name %d %s", missing.Code, missing.Body.String())
|
|
}
|
|
var verr map[string]any
|
|
if err := json.Unmarshal(missing.Body.Bytes(), &verr); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
errorsBody, _ := verr["errors"].(map[string]any)
|
|
if _, ok := errorsBody["name"]; !ok {
|
|
t.Fatalf("errors = %#v", verr)
|
|
}
|
|
}
|
|
|
|
func TestChangePassword(t *testing.T) {
|
|
app, gdb := sessionApp(t, "0s")
|
|
user := insertUser(t, gdb, "change@example.test", "correct-horse")
|
|
if err := gdb.Model(user).Update("has_self_set_password", true).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sub := strconv.FormatUint(uint64(user.ID), 10)
|
|
older := craftToken(t, sub, "older-token", time.Now().Add(-2*time.Minute), time.Now().Add(time.Hour))
|
|
if rec := bearer(t, controllers.Fetch(app), http.MethodGet, "/_user/api/v1/fetch", older); rec.Code != http.StatusOK {
|
|
t.Fatalf("older fetch before change %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
login := postJSON(t, controllers.Login(app), "/_user/api/v1/login", `{"email":"change@example.test","password":"correct-horse"}`)
|
|
var logged map[string]any
|
|
if err := json.Unmarshal(login.Body.Bytes(), &logged); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
token, _ := logged["token"].(string)
|
|
if login.Code != http.StatusOK || token == "" {
|
|
t.Fatalf("login %d %s", login.Code, login.Body.String())
|
|
}
|
|
changed := bearerJSON(t, controllers.ChangePassword(app), "/_user/api/v1/change-password", token, `{"current_password":"correct-horse","password":"brand-new-password","password_confirmation":"brand-new-password"}`)
|
|
if changed.Code != http.StatusOK || !strings.Contains(changed.Body.String(), `"message":"Password changed"`) || strings.Contains(changed.Body.String(), `"token"`) {
|
|
t.Fatalf("change %d %s", changed.Code, changed.Body.String())
|
|
}
|
|
if rec := bearer(t, controllers.Fetch(app), http.MethodGet, "/_user/api/v1/fetch", token); rec.Code != http.StatusOK {
|
|
t.Fatalf("presenting token rejected %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
if rec := bearer(t, controllers.Fetch(app), http.MethodGet, "/_user/api/v1/fetch", older); rec.Code != http.StatusUnauthorized {
|
|
t.Fatalf("older token still works %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
wrong := bearerJSON(t, controllers.ChangePassword(app), "/_user/api/v1/change-password", token, `{"current_password":"nope","password":"another-password","password_confirmation":"another-password"}`)
|
|
if wrong.Body.String() != `{"error":"Invalid email or password","errors":{"current_password":["Invalid email or password"]}}` {
|
|
t.Fatalf("wrong current %d %s", wrong.Code, wrong.Body.String())
|
|
}
|
|
same := bearerJSON(t, controllers.ChangePassword(app), "/_user/api/v1/change-password", token, `{"current_password":"brand-new-password","password":"brand-new-password","password_confirmation":"brand-new-password"}`)
|
|
if same.Code != http.StatusUnprocessableEntity {
|
|
t.Fatalf("same password %d %s", same.Code, same.Body.String())
|
|
}
|
|
|
|
locked := insertUser(t, gdb, "locked-password@example.test", "correct-horse")
|
|
if err := gdb.Model(locked).UpdateColumn("has_self_set_password", false).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
lockedLogin := postJSON(t, controllers.Login(app), "/_user/api/v1/login", `{"email":"locked-password@example.test","password":"correct-horse"}`)
|
|
var lockedBody map[string]any
|
|
if err := json.Unmarshal(lockedLogin.Body.Bytes(), &lockedBody); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
lockedToken, _ := lockedBody["token"].(string)
|
|
if lockedLogin.Code != http.StatusOK || lockedToken == "" {
|
|
t.Fatalf("locked login %d %s", lockedLogin.Code, lockedLogin.Body.String())
|
|
}
|
|
opaque := bearerJSON(t, controllers.ChangePassword(app), "/_user/api/v1/change-password", lockedToken, `{"current_password":"correct-horse","password":"brand-new-password","password_confirmation":"brand-new-password"}`)
|
|
if opaque.Code != http.StatusInternalServerError || opaque.Body.String() != `{"error":true,"message":"Internal server error"}` {
|
|
t.Fatalf("no self-set password %d %s", opaque.Code, opaque.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestMarketingConsent(t *testing.T) {
|
|
app, gdb := sessionApp(t, "0s")
|
|
token := loginToken(t, app, gdb, "consent@example.test")
|
|
on := bearerJSON(t, controllers.MarketingConsent(app), "/_user/api/v1/marketing-consent", token, `{"marketing_consent":true}`)
|
|
if on.Code != http.StatusOK || !strings.Contains(on.Body.String(), `"marketing_consent":true`) || !strings.Contains(on.Body.String(), `"message":"Marketing consent updated"`) {
|
|
t.Fatalf("on %d %s", on.Code, on.Body.String())
|
|
}
|
|
off := bearerJSON(t, controllers.MarketingConsent(app), "/_user/api/v1/marketing-consent", token, `{"marketing_consent":false}`)
|
|
if off.Code != http.StatusOK || !strings.Contains(off.Body.String(), `"marketing_consent":false`) {
|
|
t.Fatalf("off %d %s", off.Code, off.Body.String())
|
|
}
|
|
bad := bearerJSON(t, controllers.MarketingConsent(app), "/_user/api/v1/marketing-consent", token, `{"marketing_consent":"yes"}`)
|
|
if bad.Code != http.StatusUnprocessableEntity {
|
|
t.Fatalf("non-bool %d %s", bad.Code, bad.Body.String())
|
|
}
|
|
}
|