Tests[UgradeUserToPro, DowngradeUserToNonPro, FailedUgradeUserToPro, FailToCreateProUser, ReuseProToken]

This commit is contained in:
Mike Schwörer 2023-01-17 22:56:04 +01:00
parent ec9a326002
commit e7a45d9a05
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
4 changed files with 202 additions and 37 deletions

View File

@ -47,6 +47,8 @@
- endpoint to list all servernames of user (distinct select) - endpoint to list all servernames of user (distinct select)
- ios purchasw verification
#### PERSONAL #### PERSONAL
- in my script: use `srvname` for sendername - in my script: use `srvname` for sendername

View File

@ -235,23 +235,30 @@ func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
} }
if b.ProToken != nil { if b.ProToken != nil {
ptok, err := h.app.VerifyProToken(ctx, *b.ProToken) if *b.ProToken == "" {
if err != nil { err := h.database.UpdateUserProToken(ctx, u.UserID, nil)
return ginresp.APIError(g, 500, apierr.FAILED_VERIFY_PRO_TOKEN, "Failed to query purchase status", err) if err != nil {
} return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update user", err)
}
} else {
ptok, err := h.app.VerifyProToken(ctx, *b.ProToken)
if err != nil {
return ginresp.APIError(g, 500, apierr.FAILED_VERIFY_PRO_TOKEN, "Failed to query purchase status", err)
}
if !ptok { if !ptok {
return ginresp.APIError(g, 400, apierr.INVALID_PRO_TOKEN, "Purchase token could not be verified", nil) return ginresp.APIError(g, 400, apierr.INVALID_PRO_TOKEN, "Purchase token could not be verified", nil)
} }
err = h.database.ClearProTokens(ctx, *b.ProToken) err = h.database.ClearProTokens(ctx, *b.ProToken)
if err != nil { 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 fcm tokens", err)
} }
err = h.database.UpdateUserProToken(ctx, u.UserID, b.ProToken) err = h.database.UpdateUserProToken(ctx, u.UserID, b.ProToken)
if err != nil { if err != nil {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update user", err) return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update user", err)
}
} }
} }

View File

@ -810,12 +810,16 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse {
return ginresp.CompatAPIError(204, "Authentification failed") return ginresp.CompatAPIError(204, "Authentification failed")
} }
if data.ProToken != nil {
data.ProToken = langext.Ptr("ANDROID|v1|" + *data.ProToken)
}
if *data.Pro != "true" { if *data.Pro != "true" {
data.ProToken = nil data.ProToken = nil
} }
if data.ProToken != nil { if data.ProToken != nil {
ptok, err := h.app.VerifyProToken(ctx, "ANDROID|v1|"+*data.ProToken) ptok, err := h.app.VerifyProToken(ctx, *data.ProToken)
if err != nil { if err != nil {
return ginresp.CompatAPIError(0, "Failed to query purchase status") return ginresp.CompatAPIError(0, "Failed to query purchase status")
} }
@ -824,7 +828,12 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse {
return ginresp.CompatAPIError(0, "Purchase token could not be verified") return ginresp.CompatAPIError(0, "Purchase token could not be verified")
} }
err = h.database.UpdateUserProToken(ctx, user.UserID, langext.Ptr("ANDROID|v1|"+*data.ProToken)) err = h.database.ClearProTokens(ctx, *data.ProToken)
if err != nil {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to clear existing fcm tokens", err)
}
err = h.database.UpdateUserProToken(ctx, user.UserID, langext.Ptr(*data.ProToken))
if err != nil { if err != nil {
return ginresp.CompatAPIError(0, "Failed to update user") return ginresp.CompatAPIError(0, "Failed to update user")
} }

View File

@ -130,6 +130,64 @@ func TestUpdateUsername(t *testing.T) {
tt.AssertEqual(t, "username", nil, r6["username"]) tt.AssertEqual(t, "username", nil, r6["username"])
} }
func TestUgradeUserToPro(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop()
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
"no_client": true,
})
tt.AssertEqual(t, "is_pro", false, r0["is_pro"])
uid0 := fmt.Sprintf("%v", r0["user_id"])
admintok0 := r0["admin_key"].(string)
r1 := tt.RequestAuthPatch[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": "ANDROID|v2|PURCHASED:000"})
tt.AssertEqual(t, "is_pro", true, r1["is_pro"])
r2 := tt.RequestAuthGet[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0)
tt.AssertEqual(t, "is_pro", true, r2["is_pro"])
}
func TestDowngradeUserToNonPro(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop()
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
"no_client": true,
"pro_token": "ANDROID|v2|PURCHASED:UNIQ_111",
})
tt.AssertEqual(t, "is_pro", true, r0["is_pro"])
uid0 := fmt.Sprintf("%v", r0["user_id"])
admintok0 := r0["admin_key"].(string)
r1 := tt.RequestAuthPatch[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": ""})
tt.AssertEqual(t, "is_pro", false, r1["is_pro"])
r2 := tt.RequestAuthGet[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0)
tt.AssertEqual(t, "is_pro", false, r2["is_pro"])
}
func TestFailedUgradeUserToPro(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop()
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
"no_client": true,
})
tt.AssertEqual(t, "is_pro", false, r0["is_pro"])
uid0 := fmt.Sprintf("%v", r0["user_id"])
admintok0 := r0["admin_key"].(string)
tt.RequestAuthPatchShouldFail(t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": "ANDROID|v2|INVALID"}, 400, apierr.INVALID_PRO_TOKEN)
tt.RequestAuthPatchShouldFail(t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": "ANDROID|v99|PURCHASED"}, 400, apierr.INVALID_PRO_TOKEN)
tt.RequestAuthPatchShouldFail(t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": "@INVALID"}, 400, apierr.INVALID_PRO_TOKEN)
}
func TestRecreateKeys(t *testing.T) { func TestRecreateKeys(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t) _, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop() defer stop()
@ -259,30 +317,119 @@ func TestCreateProUser(t *testing.T) {
tt.AssertEqual(t, "is_pro", true, r3["is_pro"]) tt.AssertEqual(t, "is_pro", true, r3["is_pro"])
} }
}
func TestFailToCreateProUser(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop()
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)
}
func TestReuseProToken(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop()
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
"no_client": true,
})
tt.AssertEqual(t, "is_pro", false, r0["is_pro"])
uid0 := fmt.Sprintf("%v", r0["user_id"])
admintok0 := r0["admin_key"].(string)
r1 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
"no_client": true,
"pro_token": "ANDROID|v2|PURCHASED:UNIQ_1",
})
tt.AssertEqual(t, "is_pro", true, r1["is_pro"])
uid1 := fmt.Sprintf("%v", r1["user_id"])
admintok1 := r1["admin_key"].(string)
{ {
tt.RequestPostShouldFail(t, baseUrl, "/api/users", gin.H{ rc := tt.RequestAuthGet[gin.H](t, admintok1, baseUrl, "/api/users/"+uid1)
"agent_model": "DUMMY_PHONE", tt.AssertEqual(t, "is_pro", true, rc["is_pro"])
"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{ r2 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
"agent_model": "DUMMY_PHONE", "no_client": true,
"agent_version": "4X", "pro_token": "ANDROID|v2|PURCHASED:UNIQ_1",
"client_type": "ANDROID", })
"fcm_token": "DUMMY_FCM", tt.AssertEqual(t, "is_pro", true, r2["is_pro"])
"pro_token": "_",
}, 400, apierr.INVALID_PRO_TOKEN)
tt.RequestPostShouldFail(t, baseUrl, "/api/users", gin.H{ uid2 := fmt.Sprintf("%v", r2["user_id"])
"agent_model": "DUMMY_PHONE", admintok2 := r2["admin_key"].(string)
"agent_version": "4X",
"client_type": "ANDROID", {
"fcm_token": "DUMMY_FCM", rc := tt.RequestAuthGet[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0)
"pro_token": "ANDROID|v99|xxx", tt.AssertEqual(t, "is_pro", false, rc["is_pro"])
}, 400, apierr.INVALID_PRO_TOKEN) }
{
rc := tt.RequestAuthGet[gin.H](t, admintok1, baseUrl, "/api/users/"+uid1)
tt.AssertEqual(t, "is_pro", false, rc["is_pro"])
}
{
rc := tt.RequestAuthGet[gin.H](t, admintok2, baseUrl, "/api/users/"+uid2)
tt.AssertEqual(t, "is_pro", true, rc["is_pro"])
}
tt.RequestAuthPatch[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": "ANDROID|v2|PURCHASED:UNIQ_2"})
{
rc := tt.RequestAuthGet[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0)
tt.AssertEqual(t, "is_pro", true, rc["is_pro"])
}
{
rc := tt.RequestAuthGet[gin.H](t, admintok1, baseUrl, "/api/users/"+uid1)
tt.AssertEqual(t, "is_pro", false, rc["is_pro"])
}
{
rc := tt.RequestAuthGet[gin.H](t, admintok2, baseUrl, "/api/users/"+uid2)
tt.AssertEqual(t, "is_pro", true, rc["is_pro"])
}
tt.RequestAuthPatch[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0, gin.H{"pro_token": "ANDROID|v2|PURCHASED:UNIQ_1"})
{
rc := tt.RequestAuthGet[gin.H](t, admintok0, baseUrl, "/api/users/"+uid0)
tt.AssertEqual(t, "is_pro", true, rc["is_pro"])
}
{
rc := tt.RequestAuthGet[gin.H](t, admintok1, baseUrl, "/api/users/"+uid1)
tt.AssertEqual(t, "is_pro", false, rc["is_pro"])
}
{
rc := tt.RequestAuthGet[gin.H](t, admintok2, baseUrl, "/api/users/"+uid2)
tt.AssertEqual(t, "is_pro", false, rc["is_pro"])
} }
} }