Tests[TokenKeys, TokenKeysInitial, TokenKeysCreate, TokenKeysUpdate, TokenKeysDelete, TokenKeysDeleteSelf, TokenKeysDowngradeSelf, TokenKeysPermissions]
This commit is contained in:
parent
03f60ff316
commit
b1681b53e4
@ -44,7 +44,7 @@
|
|||||||
* [X] CRUD routes for keys
|
* [X] CRUD routes for keys
|
||||||
* [X] KeyToken.messagecounter
|
* [X] KeyToken.messagecounter
|
||||||
* [x] update old-data migration to create token-keys
|
* [x] update old-data migration to create token-keys
|
||||||
* [ ] unit tests
|
* [x] unit tests
|
||||||
|
|
||||||
- We no longer have a route to reshuffle all keys (previously in updateUser), add a /user/:uid/keys/reset ?
|
- We no longer have a route to reshuffle all keys (previously in updateUser), add a /user/:uid/keys/reset ?
|
||||||
Would delete all existing keys and create 3 new ones?
|
Would delete all existing keys and create 3 new ones?
|
||||||
|
@ -44,6 +44,7 @@ const (
|
|||||||
|
|
||||||
CHANNEL_ALREADY_EXISTS APIError = 1501
|
CHANNEL_ALREADY_EXISTS APIError = 1501
|
||||||
CANNOT_SELFDELETE_KEY APIError = 1511
|
CANNOT_SELFDELETE_KEY APIError = 1511
|
||||||
|
CANNOT_SELFUPDATE_KEY APIError = 1512
|
||||||
|
|
||||||
QUOTA_REACHED APIError = 2101
|
QUOTA_REACHED APIError = 2101
|
||||||
|
|
||||||
|
@ -201,10 +201,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Param uid path int true "UserID"
|
// @Param uid path int true "UserID"
|
||||||
//
|
//
|
||||||
// @Param username body string false "Change the username (send an empty string to clear it)"
|
// @Param username body string false "Change the username (send an empty string to clear it)"
|
||||||
// @Param pro_token body string false "Send a verification of permium purchase"
|
// @Param pro_token body string false "Send a verification of premium purchase"
|
||||||
// @Param read_key body string false "Send `true` to create a new read_key"
|
|
||||||
// @Param send_key body string false "Send `true` to create a new send_key"
|
|
||||||
// @Param admin_key body string false "Send `true` to create a new admin_key"
|
|
||||||
//
|
//
|
||||||
// @Success 200 {object} models.UserJSON
|
// @Success 200 {object} models.UserJSON
|
||||||
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
||||||
@ -1619,7 +1616,7 @@ func (h APIHandler) GetUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
return *permResp
|
return *permResp
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := h.database.GetKeyToken(ctx, u.UserID, u.KeyID)
|
keytoken, err := h.database.GetKeyToken(ctx, u.UserID, u.KeyID)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.APIError(g, 404, apierr.KEY_NOT_FOUND, "Key not found", err)
|
return ginresp.APIError(g, 404, apierr.KEY_NOT_FOUND, "Key not found", err)
|
||||||
}
|
}
|
||||||
@ -1627,7 +1624,7 @@ func (h APIHandler) GetUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query client", err)
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query client", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, client.JSON()))
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, keytoken.JSON()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserKey swaggerdoc
|
// UpdateUserKey swaggerdoc
|
||||||
@ -1639,6 +1636,8 @@ func (h APIHandler) GetUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Param uid path int true "UserID"
|
// @Param uid path int true "UserID"
|
||||||
// @Param kid path int true "TokenKeyID"
|
// @Param kid path int true "TokenKeyID"
|
||||||
//
|
//
|
||||||
|
// @Param post_body body handler.UpdateUserKey.body false " "
|
||||||
|
//
|
||||||
// @Success 200 {object} models.KeyTokenJSON
|
// @Success 200 {object} models.KeyTokenJSON
|
||||||
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
||||||
// @Failure 401 {object} ginresp.apiError "user is not authorized / has missing permissions"
|
// @Failure 401 {object} ginresp.apiError "user is not authorized / has missing permissions"
|
||||||
@ -1670,7 +1669,7 @@ func (h APIHandler) UpdateUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
return *permResp
|
return *permResp
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := h.database.GetKeyToken(ctx, u.UserID, u.KeyID)
|
keytoken, err := h.database.GetKeyToken(ctx, u.UserID, u.KeyID)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.APIError(g, 404, apierr.KEY_NOT_FOUND, "Key not found", err)
|
return ginresp.APIError(g, 404, apierr.KEY_NOT_FOUND, "Key not found", err)
|
||||||
}
|
}
|
||||||
@ -1683,30 +1682,47 @@ func (h APIHandler) UpdateUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update name", err)
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update name", err)
|
||||||
}
|
}
|
||||||
|
keytoken.Name = *b.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Permissions != nil {
|
if b.Permissions != nil {
|
||||||
err := h.database.UpdateKeyTokenPermissions(ctx, u.KeyID, models.ParseTokenPermissionList(*b.Permissions))
|
if keytoken.KeyTokenID == *ctx.GetPermissionKeyTokenID() {
|
||||||
|
return ginresp.APIError(g, 400, apierr.CANNOT_SELFUPDATE_KEY, "Cannot update the currently used key", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
permlist := models.ParseTokenPermissionList(*b.Permissions)
|
||||||
|
err := h.database.UpdateKeyTokenPermissions(ctx, u.KeyID, permlist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update permissions", err)
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update permissions", err)
|
||||||
}
|
}
|
||||||
|
keytoken.Permissions = permlist
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.AllChannels != nil {
|
if b.AllChannels != nil {
|
||||||
|
if keytoken.KeyTokenID == *ctx.GetPermissionKeyTokenID() {
|
||||||
|
return ginresp.APIError(g, 400, apierr.CANNOT_SELFUPDATE_KEY, "Cannot update the currently used key", err)
|
||||||
|
}
|
||||||
|
|
||||||
err := h.database.UpdateKeyTokenAllChannels(ctx, u.KeyID, *b.AllChannels)
|
err := h.database.UpdateKeyTokenAllChannels(ctx, u.KeyID, *b.AllChannels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update all_channels", err)
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update all_channels", err)
|
||||||
}
|
}
|
||||||
|
keytoken.AllChannels = *b.AllChannels
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Channels != nil {
|
if b.Channels != nil {
|
||||||
|
if keytoken.KeyTokenID == *ctx.GetPermissionKeyTokenID() {
|
||||||
|
return ginresp.APIError(g, 400, apierr.CANNOT_SELFUPDATE_KEY, "Cannot update the currently used key", err)
|
||||||
|
}
|
||||||
|
|
||||||
err := h.database.UpdateKeyTokenChannels(ctx, u.KeyID, *b.Channels)
|
err := h.database.UpdateKeyTokenChannels(ctx, u.KeyID, *b.Channels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update channels", err)
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update channels", err)
|
||||||
}
|
}
|
||||||
|
keytoken.Channels = *b.Channels
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, client.JSON()))
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, keytoken.JSON()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUserKey swaggerdoc
|
// CreateUserKey swaggerdoc
|
||||||
@ -1810,7 +1826,7 @@ func (h APIHandler) DeleteUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if u.KeyID == *ctx.GetPermissionKeyTokenID() {
|
if u.KeyID == *ctx.GetPermissionKeyTokenID() {
|
||||||
return ginresp.APIError(g, 404, apierr.CANNOT_SELFDELETE_KEY, "Cannot delete the currently used key", err)
|
return ginresp.APIError(g, 400, apierr.CANNOT_SELFDELETE_KEY, "Cannot delete the currently used key", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.database.DeleteKeyToken(ctx, u.KeyID)
|
err = h.database.DeleteKeyToken(ctx, u.KeyID)
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListUserKeys(t *testing.T) {
|
func TestTokenKeys(t *testing.T) {
|
||||||
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
data := tt.InitSingleData(t, ws)
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
type keylist struct {
|
type keyobj struct {
|
||||||
Tokens []struct {
|
|
||||||
AllChannels bool `json:"all_channels"`
|
AllChannels bool `json:"all_channels"`
|
||||||
Channels []string `json:"channels"`
|
Channels []string `json:"channels"`
|
||||||
KeytokenId string `json:"keytoken_id"`
|
KeytokenId string `json:"keytoken_id"`
|
||||||
@ -21,36 +22,472 @@ func TestListUserKeys(t *testing.T) {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
OwnerUserId string `json:"owner_user_id"`
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
Permissions string `json:"permissions"`
|
Permissions string `json:"permissions"`
|
||||||
} `json:"tokens"`
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 3, len(klist.Keys))
|
||||||
|
|
||||||
|
tt.AssertArrAny(t, "keys->any[Admin]", klist.Keys, func(s keyobj) bool {
|
||||||
|
return s.AllChannels == true && s.Name == "AdminKey (default)" && s.Permissions == "A"
|
||||||
|
})
|
||||||
|
tt.AssertArrAny(t, "keys->any[Send]", klist.Keys, func(s keyobj) bool {
|
||||||
|
return s.AllChannels == true && s.Name == "SendKey (default)" && s.Permissions == "CS"
|
||||||
|
})
|
||||||
|
tt.AssertArrAny(t, "keys->any[Read]", klist.Keys, func(s keyobj) bool {
|
||||||
|
return s.AllChannels == true && s.Name == "ReadKey (default)" && s.Permissions == "UR;CR"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
key2 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "Admin2",
|
||||||
|
"permissions": "A",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key2.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key2.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key2.AllChannels)
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 4, len(klist.Keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
key3 := tt.RequestAuthGet[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key2.KeytokenId))
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "KeytokenId", key2.KeytokenId, key3.KeytokenId)
|
||||||
|
tt.AssertEqual(t, "UserID", data.UserID, key3.OwnerUserId)
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key3.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key3.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key3.AllChannels)
|
||||||
|
|
||||||
|
tt.RequestAuthDelete[tt.Void](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key2.KeytokenId), gin.H{})
|
||||||
|
|
||||||
|
tt.RequestAuthGetShouldFail(t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key2.KeytokenId), 404, apierr.KEY_NOT_FOUND)
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 3, len(klist.Keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
chan0 := tt.RequestAuthPost[gin.H](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/channels", data.UserID), gin.H{
|
||||||
|
"name": "testchan1",
|
||||||
|
})
|
||||||
|
chanid := fmt.Sprintf("%v", chan0["channel_id"])
|
||||||
|
|
||||||
|
key4 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": false,
|
||||||
|
"channels": []string{chanid},
|
||||||
|
"name": "TKey1",
|
||||||
|
"permissions": "CS",
|
||||||
|
})
|
||||||
|
tt.AssertEqual(t, "Name", "TKey1", key4.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "CS", key4.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", false, key4.AllChannels)
|
||||||
|
tt.AssertStrRepEqual(t, "Channels", []string{chanid}, key4.Channels)
|
||||||
|
|
||||||
|
key5 := tt.RequestAuthPatch[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key4.KeytokenId), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "TKey2-A",
|
||||||
|
"permissions": "A",
|
||||||
|
})
|
||||||
|
tt.AssertEqual(t, "Name", "TKey2-A", key5.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key5.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key5.AllChannels)
|
||||||
|
tt.AssertStrRepEqual(t, "Channels", []string{}, key5.Channels)
|
||||||
|
|
||||||
|
key6 := tt.RequestAuthGet[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key5.KeytokenId))
|
||||||
|
tt.AssertEqual(t, "Name", "TKey2-A", key6.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key6.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key6.AllChannels)
|
||||||
|
tt.AssertStrRepEqual(t, "Channels", []string{}, key6.Channels)
|
||||||
|
|
||||||
|
key7 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": false,
|
||||||
|
"channels": []string{chanid},
|
||||||
|
"name": "TKey7",
|
||||||
|
"permissions": "CS",
|
||||||
|
})
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 5, len(klist.Keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
msg1s := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||||
|
"key": key7.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"channel": "testchan1",
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
})
|
||||||
|
|
||||||
|
msg1 := tt.RequestAuthGet[gin.H](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/messages/%s", msg1s["scn_msg_id"]))
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "AllChannels", key7.KeytokenId, msg1["used_key_id"])
|
||||||
|
|
||||||
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
|
"key": key7.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"channel": "testchan2",
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
}, 401, apierr.USER_AUTH_FAILED) // wrong channel
|
||||||
|
|
||||||
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
|
"key": key7.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
}, 401, apierr.USER_AUTH_FAILED) // no channel (=main)
|
||||||
|
|
||||||
|
tt.RequestAuthGetShouldFail(t, key7.Token, baseUrl, fmt.Sprintf("/api/v2/users/%s", data.UserID), 401, apierr.USER_AUTH_FAILED) // no user read perm
|
||||||
|
|
||||||
|
tt.RequestAuthPatchShouldFail(t, key7.Token, baseUrl, "/api/v2/users/"+data.UserID, gin.H{"username": "my_user_001"}, 401, apierr.USER_AUTH_FAILED) // no user update perm
|
||||||
|
|
||||||
|
key8 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "TKey7",
|
||||||
|
"permissions": "CR",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
|
"key": key8.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
}, 401, apierr.USER_AUTH_FAILED) // no send perm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTokenKeysInitial(t *testing.T) {
|
||||||
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 3, len(klist.Keys))
|
||||||
|
|
||||||
|
tt.AssertArrAny(t, "keys->any[Admin]", klist.Keys, func(s keyobj) bool {
|
||||||
|
return s.AllChannels == true && s.Name == "AdminKey (default)" && s.Permissions == "A"
|
||||||
|
})
|
||||||
|
tt.AssertArrAny(t, "keys->any[Send]", klist.Keys, func(s keyobj) bool {
|
||||||
|
return s.AllChannels == true && s.Name == "SendKey (default)" && s.Permissions == "CS"
|
||||||
|
})
|
||||||
|
tt.AssertArrAny(t, "keys->any[Read]", klist.Keys, func(s keyobj) bool {
|
||||||
|
return s.AllChannels == true && s.Name == "ReadKey (default)" && s.Permissions == "UR;CR"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTokenKeysCreate(t *testing.T) {
|
||||||
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
key2 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "Admin2",
|
||||||
|
"permissions": "A",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key2.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key2.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key2.AllChannels)
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 4, len(klist.Keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
key3 := tt.RequestAuthGet[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key2.KeytokenId))
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "KeytokenId", key2.KeytokenId, key3.KeytokenId)
|
||||||
|
tt.AssertEqual(t, "UserID", data.UserID, key3.OwnerUserId)
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key3.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key3.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key3.AllChannels)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTokenKeysUpdate(t *testing.T) {
|
||||||
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
key2 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "Admin2",
|
||||||
|
"permissions": "A",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key2.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key2.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key2.AllChannels)
|
||||||
|
|
||||||
|
key3 := tt.RequestAuthGet[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key2.KeytokenId))
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "KeytokenId", key2.KeytokenId, key3.KeytokenId)
|
||||||
|
tt.AssertEqual(t, "UserID", data.UserID, key3.OwnerUserId)
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key3.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key3.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key3.AllChannels)
|
||||||
|
|
||||||
|
key5 := tt.RequestAuthPatch[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key3.KeytokenId), gin.H{
|
||||||
|
"name": "Hello",
|
||||||
|
})
|
||||||
|
tt.AssertEqual(t, "Name", "Hello", key5.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key5.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key5.AllChannels)
|
||||||
|
tt.AssertStrRepEqual(t, "Channels", []string{}, key5.Channels)
|
||||||
|
|
||||||
|
key6 := tt.RequestAuthGet[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key5.KeytokenId))
|
||||||
|
tt.AssertEqual(t, "Name", "Hello", key6.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key6.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key6.AllChannels)
|
||||||
|
tt.AssertStrRepEqual(t, "Channels", []string{}, key6.Channels)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTokenKeysDelete(t *testing.T) {
|
||||||
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
key2 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "Admin2",
|
||||||
|
"permissions": "A",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "Name", "Admin2", key2.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", key2.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, key2.AllChannels)
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 4, len(klist.Keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.RequestAuthDelete[tt.Void](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, key2.KeytokenId), gin.H{})
|
||||||
|
|
||||||
|
{
|
||||||
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
tt.AssertEqual(t, "len(keys)", 3, len(klist.Keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTokenKeysDeleteSelf(t *testing.T) {
|
||||||
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
|
|
||||||
tt.AssertEqual(t, "len(keys)", 1, len(klist.Tokens))
|
ak := ""
|
||||||
|
for _, v := range klist.Keys {
|
||||||
t.SkipNow() //TODO
|
if v.Permissions == "A" {
|
||||||
|
ak = v.KeytokenId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateUserKey(t *testing.T) {
|
tt.RequestAuthDeleteShouldFail(t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, ak), gin.H{}, 400, apierr.CANNOT_SELFDELETE_KEY)
|
||||||
t.SkipNow() //TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteUserKey(t *testing.T) {
|
func TestTokenKeysDowngradeSelf(t *testing.T) {
|
||||||
t.SkipNow() //TODO
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
|
}
|
||||||
|
type keylist struct {
|
||||||
|
Keys []keyobj `json:"keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetUserKey(t *testing.T) {
|
klist := tt.RequestAuthGet[keylist](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID))
|
||||||
t.SkipNow() //TODO
|
|
||||||
|
ak := ""
|
||||||
|
for _, v := range klist.Keys {
|
||||||
|
if v.Permissions == "A" {
|
||||||
|
ak = v.KeytokenId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateUserKey(t *testing.T) {
|
tt.RequestAuthPatchShouldFail(t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, ak), gin.H{
|
||||||
t.SkipNow() //TODO
|
"permissions": "CR",
|
||||||
|
}, 400, apierr.CANNOT_SELFUPDATE_KEY)
|
||||||
|
|
||||||
|
tt.RequestAuthPatchShouldFail(t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, ak), gin.H{
|
||||||
|
"all_channels": false,
|
||||||
|
}, 400, apierr.CANNOT_SELFUPDATE_KEY)
|
||||||
|
|
||||||
|
tt.RequestAuthPatchShouldFail(t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, ak), gin.H{
|
||||||
|
"channels": []string{"main"},
|
||||||
|
}, 400, apierr.CANNOT_SELFUPDATE_KEY)
|
||||||
|
|
||||||
|
tt.RequestAuthPatch[tt.Void](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, ak), gin.H{
|
||||||
|
"name": "This-is-allowed",
|
||||||
|
})
|
||||||
|
|
||||||
|
keyOut := tt.RequestAuthGet[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UserID, ak))
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "UserID", data.UserID, keyOut.OwnerUserId)
|
||||||
|
tt.AssertEqual(t, "Name", "This-is-allowed", keyOut.Name)
|
||||||
|
tt.AssertEqual(t, "Permissions", "A", keyOut.Permissions)
|
||||||
|
tt.AssertEqual(t, "AllChannels", true, keyOut.AllChannels)
|
||||||
|
tt.AssertStrRepEqual(t, "Channels", []string{}, keyOut.Channels)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserKeyPermissions(t *testing.T) {
|
func TestTokenKeysPermissions(t *testing.T) {
|
||||||
t.SkipNow() //TODO
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
AllChannels bool `json:"all_channels"`
|
||||||
|
Channels []string `json:"channels"`
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
MessagesSent int `json:"messages_sent"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OwnerUserId string `json:"owner_user_id"`
|
||||||
|
Permissions string `json:"permissions"`
|
||||||
|
Token string `json:"token"` // only in create
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUsedKeyInMessage(t *testing.T) {
|
chan0 := tt.RequestAuthPost[gin.H](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/channels", data.UserID), gin.H{
|
||||||
t.SkipNow() //TODO
|
"name": "testchan1",
|
||||||
|
})
|
||||||
|
chanid := fmt.Sprintf("%v", chan0["channel_id"])
|
||||||
|
|
||||||
|
key7 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": false,
|
||||||
|
"channels": []string{chanid},
|
||||||
|
"name": "TKey7",
|
||||||
|
"permissions": "CS",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
|
"key": key7.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"channel": "testchan2",
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
}, 401, apierr.USER_AUTH_FAILED) // wrong channel
|
||||||
|
|
||||||
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
|
"key": key7.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
}, 401, apierr.USER_AUTH_FAILED) // no channel (=main)
|
||||||
|
|
||||||
|
tt.RequestAuthGetShouldFail(t, key7.Token, baseUrl, fmt.Sprintf("/api/v2/users/%s", data.UserID), 401, apierr.USER_AUTH_FAILED) // no user read perm
|
||||||
|
|
||||||
|
tt.RequestAuthPatchShouldFail(t, key7.Token, baseUrl, "/api/v2/users/"+data.UserID, gin.H{"username": "my_user_001"}, 401, apierr.USER_AUTH_FAILED) // no user update perm
|
||||||
|
|
||||||
|
key8 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UserID), gin.H{
|
||||||
|
"all_channels": true,
|
||||||
|
"channels": []string{},
|
||||||
|
"name": "TKey7",
|
||||||
|
"permissions": "CR",
|
||||||
|
})
|
||||||
|
|
||||||
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
|
"key": key8.Token,
|
||||||
|
"user_id": data.UserID,
|
||||||
|
"title": "HelloWorld_001",
|
||||||
|
}, 401, apierr.USER_AUTH_FAILED) // no send perm
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user