diff --git a/scnserver/api/handler/api.go b/scnserver/api/handler/api.go index b38a456..761cc4c 100644 --- a/scnserver/api/handler/api.go +++ b/scnserver/api/handler/api.go @@ -102,7 +102,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse { if b.ProToken != nil { err := h.database.ClearProTokens(ctx, *b.ProToken) if err != nil { - return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to clear existing fcm tokens", err) + return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to clear existing pro tokens", err) } } diff --git a/scnserver/api/handler/compat.go b/scnserver/api/handler/compat.go index b91307d..1a3ca5d 100644 --- a/scnserver/api/handler/compat.go +++ b/scnserver/api/handler/compat.go @@ -194,12 +194,16 @@ func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(0, "Missing parameter [[pro_token]]") } + if data.ProToken != nil { + data.ProToken = langext.Ptr("ANDROID|v1|" + *data.ProToken) + } + if *data.Pro != "true" { data.ProToken = nil } if data.ProToken != nil { - ptok, err := h.app.VerifyProToken(ctx, "ANDROID|v2|"+*data.ProToken) + ptok, err := h.app.VerifyProToken(ctx, *data.ProToken) if err != nil { return ginresp.CompatAPIError(0, "Failed to query purchase status") } @@ -221,7 +225,7 @@ func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse { if data.ProToken != nil { err := h.database.ClearProTokens(ctx, *data.ProToken) if err != nil { - return ginresp.CompatAPIError(0, "Failed to clear existing fcm tokens") + return ginresp.CompatAPIError(0, "Failed to clear existing pro tokens") } } @@ -230,7 +234,7 @@ func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(0, "Failed to create user in db") } - _, err = h.database.CreateClient(ctx, user.UserID, models.ClientTypeAndroid, "ANDROID|v1|"+*data.FCMToken, "compat", "compat") + _, err = h.database.CreateClient(ctx, user.UserID, models.ClientTypeAndroid, *data.FCMToken, "compat", "compat") if err != nil { return ginresp.CompatAPIError(0, "Failed to create client in db") } @@ -599,7 +603,7 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse { } - _, err = h.database.CreateClient(ctx, user.UserID, models.ClientTypeAndroid, "ANDROID|v1|"+*data.FCMToken, "compat", "compat") + _, err = h.database.CreateClient(ctx, user.UserID, models.ClientTypeAndroid, *data.FCMToken, "compat", "compat") if err != nil { return ginresp.CompatAPIError(0, "Failed to delete client") } @@ -811,7 +815,7 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse { } if data.ProToken != nil { - ptok, err := h.app.VerifyProToken(ctx, "ANDROID|v2|"+*data.ProToken) + ptok, err := h.app.VerifyProToken(ctx, "ANDROID|v1|"+*data.ProToken) if err != nil { return ginresp.CompatAPIError(0, "Failed to query purchase status") } @@ -820,7 +824,7 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(0, "Purchase token could not be verified") } - err = h.database.UpdateUserProToken(ctx, user.UserID, data.ProToken) + err = h.database.UpdateUserProToken(ctx, user.UserID, langext.Ptr("ANDROID|v1|"+*data.ProToken)) if err != nil { return ginresp.CompatAPIError(0, "Failed to update user") } diff --git a/scnserver/logic/application.go b/scnserver/logic/application.go index 943dbc7..4fc9721 100644 --- a/scnserver/logic/application.go +++ b/scnserver/logic/application.go @@ -8,6 +8,7 @@ import ( "blackforestbytes.com/simplecloudnotifier/models" "blackforestbytes.com/simplecloudnotifier/push" "context" + "errors" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/rs/zerolog/log" @@ -166,14 +167,21 @@ func (app *Application) QuotaMax(ispro bool) int { } func (app *Application) VerifyProToken(ctx *AppContext, token string) (bool, error) { + if strings.HasPrefix(token, "ANDROID|v1|") { - subToken := token[len("ANDROID|v2|"):] + subToken := token[len("ANDROID|v1|"):] return app.VerifyAndroidProToken(ctx, subToken) } + if strings.HasPrefix(token, "ANDROID|v2|") { subToken := token[len("ANDROID|v2|"):] return app.VerifyAndroidProToken(ctx, subToken) } + + if strings.HasPrefix(token, "IOS|v1|") { + return false, errors.New("invalid token-version: ios-v1") + } + if strings.HasPrefix(token, "IOS|v2|") { subToken := token[len("IOS|v2|"):] return app.VerifyIOSProToken(ctx, subToken) diff --git a/scnserver/test/compat_test.go b/scnserver/test/compat_test.go index 8a5c0d7..1ec35df 100644 --- a/scnserver/test/compat_test.go +++ b/scnserver/test/compat_test.go @@ -308,6 +308,25 @@ func TestCompatRegister(t *testing.T) { r0 := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/register.php?fcm_token=%s&pro=%s&pro_token=%s", "DUMMY_FCM", "0", "")) tt.AssertEqual(t, "success", true, r0["success"]) + tt.AssertEqual(t, "message", "New user registered", r0["message"]) + tt.AssertEqual(t, "quota", 0, r0["quota"]) + tt.AssertEqual(t, "quota_max", 50, r0["quota_max"]) + tt.AssertEqual(t, "is_pro", 0, r0["is_pro"]) +} + +func TestCompatRegisterPro(t *testing.T) { + _, baseUrl, stop := tt.StartSimpleWebserver(t) + defer stop() + + r0 := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/register.php?fcm_token=%s&pro=%s&pro_token=%s", "DUMMY_FCM", "true", url.QueryEscape("PURCHASED:000"))) + tt.AssertEqual(t, "success", true, r0["success"]) + tt.AssertEqual(t, "message", "New user registered", r0["message"]) + tt.AssertEqual(t, "quota", 0, r0["quota"]) + tt.AssertEqual(t, "quota_max", 1000, r0["quota_max"]) + tt.AssertEqual(t, "is_pro", 1, r0["is_pro"]) + + r1 := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/register.php?fcm_token=%s&pro=%s&pro_token=%s", "DUMMY_FCM", "true", url.QueryEscape("INVALID"))) + tt.AssertEqual(t, "success", false, r1["success"]) } func TestCompatInfo(t *testing.T) { diff --git a/scnserver/test/user_test.go b/scnserver/test/user_test.go index 682d4f4..d0427d4 100644 --- a/scnserver/test/user_test.go +++ b/scnserver/test/user_test.go @@ -259,4 +259,30 @@ func TestCreateProUser(t *testing.T) { tt.AssertEqual(t, "is_pro", true, r3["is_pro"]) } + { + tt.RequestPostShouldFail(t, baseUrl, "/api/users", gin.H{ + "agent_model": "DUMMY_PHONE", + "agent_version": "4X", + "client_type": "ANDROID", + "fcm_token": "DUMMY_FCM", + "pro_token": "ANDROID|v2|INVALID", + }, 400, apierr.INVALID_PRO_TOKEN) + + tt.RequestPostShouldFail(t, baseUrl, "/api/users", gin.H{ + "agent_model": "DUMMY_PHONE", + "agent_version": "4X", + "client_type": "ANDROID", + "fcm_token": "DUMMY_FCM", + "pro_token": "_", + }, 400, apierr.INVALID_PRO_TOKEN) + + tt.RequestPostShouldFail(t, baseUrl, "/api/users", gin.H{ + "agent_model": "DUMMY_PHONE", + "agent_version": "4X", + "client_type": "ANDROID", + "fcm_token": "DUMMY_FCM", + "pro_token": "ANDROID|v99|xxx", + }, 400, apierr.INVALID_PRO_TOKEN) + } + }