Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
244 lines
8.0 KiB
Go
244 lines
8.0 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package model
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestSessionIsValid(t *testing.T) {
|
|
tcs := []struct {
|
|
name string
|
|
input Session
|
|
expectedError string
|
|
}{
|
|
{
|
|
"Invalid Id",
|
|
Session{},
|
|
"model.session.is_valid.id.app_error",
|
|
},
|
|
{
|
|
"Invalid UserId",
|
|
Session{
|
|
Id: NewId(),
|
|
},
|
|
"model.session.is_valid.user_id.app_error",
|
|
},
|
|
{
|
|
"Invalid CreateAt",
|
|
Session{
|
|
Id: NewId(),
|
|
UserId: NewId(),
|
|
},
|
|
"model.session.is_valid.create_at.app_error",
|
|
},
|
|
{
|
|
"Invalid Roles",
|
|
Session{
|
|
Id: NewId(),
|
|
UserId: NewId(),
|
|
CreateAt: 1000,
|
|
Roles: strings.Repeat("a", UserRolesMaxLength+1),
|
|
},
|
|
"model.session.is_valid.roles_limit.app_error",
|
|
},
|
|
{
|
|
"Valid",
|
|
Session{
|
|
Id: NewId(),
|
|
UserId: NewId(),
|
|
CreateAt: 1000,
|
|
Roles: strings.Repeat("a", UserRolesMaxLength),
|
|
},
|
|
"",
|
|
},
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
appErr := tc.input.IsValid()
|
|
if tc.expectedError != "" {
|
|
require.NotNil(t, appErr)
|
|
require.Equal(t, tc.expectedError, appErr.Id)
|
|
} else {
|
|
require.Nil(t, appErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSessionDeepCopy(t *testing.T) {
|
|
sessionId := NewId()
|
|
userId := NewId()
|
|
mapKey := "key"
|
|
mapValue := "val"
|
|
|
|
session := &Session{Id: sessionId, Props: map[string]string{mapKey: mapValue}, TeamMembers: []*TeamMember{{UserId: userId, TeamId: "someteamId"}}}
|
|
|
|
copySession := session.DeepCopy()
|
|
copySession.Id = "changed"
|
|
copySession.Props[mapKey] = "changed"
|
|
copySession.TeamMembers[0].UserId = "changed"
|
|
|
|
assert.Equal(t, sessionId, session.Id)
|
|
assert.Equal(t, mapValue, session.Props[mapKey])
|
|
assert.Equal(t, userId, session.TeamMembers[0].UserId)
|
|
|
|
session = &Session{Id: sessionId}
|
|
copySession = session.DeepCopy()
|
|
|
|
assert.Equal(t, sessionId, copySession.Id)
|
|
|
|
session = &Session{TeamMembers: []*TeamMember{}}
|
|
copySession = session.DeepCopy()
|
|
|
|
assert.Empty(t, copySession.TeamMembers)
|
|
}
|
|
|
|
func TestSessionCSRF(t *testing.T) {
|
|
s := Session{}
|
|
token := s.GetCSRF()
|
|
assert.Empty(t, token)
|
|
|
|
token = s.GenerateCSRF()
|
|
assert.NotEmpty(t, token)
|
|
|
|
token2 := s.GetCSRF()
|
|
assert.NotEmpty(t, token2)
|
|
assert.Equal(t, token, token2)
|
|
}
|
|
|
|
func TestSessionIsOAuthUser(t *testing.T) {
|
|
testCases := []struct {
|
|
Description string
|
|
Session Session
|
|
isOAuthUser bool
|
|
}{
|
|
{"False on empty props", Session{}, false},
|
|
{"True when key is set to true", Session{Props: StringMap{UserAuthServiceIsOAuth: strconv.FormatBool(true)}}, true},
|
|
{"False when key is set to false", Session{Props: StringMap{UserAuthServiceIsOAuth: strconv.FormatBool(false)}}, false},
|
|
{"Not affected by Session.IsOAuth being true", Session{IsOAuth: true}, false},
|
|
{"Not affected by Session.IsOAuth being false", Session{IsOAuth: false, Props: StringMap{UserAuthServiceIsOAuth: strconv.FormatBool(true)}}, true},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.Description, func(t *testing.T) {
|
|
require.Equal(t, tc.isOAuthUser, tc.Session.IsOAuthUser())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsIntegration(t *testing.T) {
|
|
testCases := []struct {
|
|
Description string
|
|
Session Session
|
|
IsIntegration bool
|
|
}{
|
|
{"False on empty props", Session{}, false},
|
|
{"True when is OAuth App", Session{IsOAuth: true}, true},
|
|
{"True when session is bot", Session{Props: StringMap{SessionPropIsBot: SessionPropIsBotValue}}, true},
|
|
{"True when session is user access token", Session{Props: StringMap{SessionPropType: SessionTypeUserAccessToken}}, true},
|
|
{"Not affected by Props[UserAuthServiceIsOAuth]", Session{Props: StringMap{UserAuthServiceIsOAuth: strconv.FormatBool(true)}}, false},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.Description, func(t *testing.T) {
|
|
require.Equal(t, tc.IsIntegration, tc.Session.IsIntegration())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsValidVoIPDeviceId(t *testing.T) {
|
|
testCases := []struct {
|
|
Description string
|
|
Value string
|
|
Valid bool
|
|
}{
|
|
{"empty string", "", false},
|
|
{"missing token", PushNotifyAppleReactNative + ":", false},
|
|
{"missing separator", PushNotifyAppleReactNative, false},
|
|
{"missing platform", ":abcd", false},
|
|
{"android is not VoIP-capable yet", PushNotifyAndroidReactNative + ":abcd", false},
|
|
{"legacy bare apple prefix not allowed", "apple:abcd", false},
|
|
{"valid apple_rn", PushNotifyAppleReactNative + ":abcd", true},
|
|
{"valid apple_rnbeta", PushNotifyAppleReactNative + "beta:abcd", true},
|
|
{"apple_rn-v2 tolerated", PushNotifyAppleReactNative + "-v2:abcd", true},
|
|
{"apple_rn-v0 tolerated", PushNotifyAppleReactNative + "-v0:abcd", true},
|
|
{"apple_rn-v999 tolerated", PushNotifyAppleReactNative + "-v999:abcd", true},
|
|
{"apple_rn-voip is not stripped and fails allowlist", PushNotifyAppleReactNative + "-voip:abcd", false},
|
|
{"apple_rn-vabc is not stripped and fails allowlist", PushNotifyAppleReactNative + "-vabc:abcd", false},
|
|
{"apple_rn-v with empty version is not stripped and fails allowlist", PushNotifyAppleReactNative + "-v:abcd", false},
|
|
{"apple_rn-v-2 with negative version is not stripped and fails allowlist", PushNotifyAppleReactNative + "-v-2:abcd", false},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.Description, func(t *testing.T) {
|
|
assert.Equal(t, tc.Valid, IsValidVoIPDeviceId(tc.Value))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsValidStandardDeviceId(t *testing.T) {
|
|
testCases := []struct {
|
|
Description string
|
|
Value string
|
|
Valid bool
|
|
}{
|
|
{"empty string", "", false},
|
|
{"missing token", PushNotifyAppleReactNative + ":", false},
|
|
{"missing separator", PushNotifyAppleReactNative, false},
|
|
{"missing platform", ":abcd", false},
|
|
{"legacy bare apple prefix not allowed", "apple:abcd", false},
|
|
{"legacy bare android prefix not allowed", "android:abcd", false},
|
|
{"valid apple_rn", PushNotifyAppleReactNative + ":abcd", true},
|
|
{"valid apple_rnbeta", PushNotifyAppleReactNative + "beta:abcd", true},
|
|
{"valid android_rn", PushNotifyAndroidReactNative + ":abcd", true},
|
|
// Mobile encodes the app-version it speaks in a "-v<N>" suffix on
|
|
// the platform (proxy strips it). Validator must tolerate it.
|
|
{"apple_rn-v2", PushNotifyAppleReactNative + "-v2:abcd", true},
|
|
{"apple_rnbeta-v2", PushNotifyAppleReactNative + "beta-v2:abcd", true},
|
|
{"android_rn-v2", PushNotifyAndroidReactNative + "-v2:abcd", true},
|
|
{"unknown platform with -v2", "foo_rn-v2:abcd", false},
|
|
{"apple_rn-v0", PushNotifyAppleReactNative + "-v0:abcd", true},
|
|
{"apple_rn-v999", PushNotifyAppleReactNative + "-v999:abcd", true},
|
|
{"apple_rn-voip not stripped, fails allowlist", PushNotifyAppleReactNative + "-voip:abcd", false},
|
|
{"apple_rn-vabc not stripped, fails allowlist", PushNotifyAppleReactNative + "-vabc:abcd", false},
|
|
{"apple_rn-v with empty version not stripped", PushNotifyAppleReactNative + "-v:abcd", false},
|
|
{"apple_rn-v-2 with negative version not stripped", PushNotifyAppleReactNative + "-v-2:abcd", false},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.Description, func(t *testing.T) {
|
|
assert.Equal(t, tc.Valid, IsValidStandardDeviceId(tc.Value))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRedactDeviceId(t *testing.T) {
|
|
testCases := []struct {
|
|
Name string
|
|
Input string
|
|
Expected string
|
|
}{
|
|
{"empty", "", ""},
|
|
{"no colon", "apple_rn", "apple_rn"},
|
|
{"empty token after colon", "apple_rn:", "apple_rn"},
|
|
{"short token passes through", PushNotifyAppleReactNative + ":1234", PushNotifyAppleReactNative + ":1234"},
|
|
{"16-char token passes through", PushNotifyAppleReactNative + ":0123456789abcdef", PushNotifyAppleReactNative + ":0123456789abcdef"},
|
|
{"17-char token truncated", PushNotifyAppleReactNative + ":0123456789abcdefg", PushNotifyAppleReactNative + ":0123456789abcdef…"},
|
|
{"long token truncated", PushNotifyAndroidReactNative + ":abcdef0123456789cafebabe1234", PushNotifyAndroidReactNative + ":abcdef0123456789…"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
assert.Equal(t, tc.Expected, RedactDeviceId(tc.Input))
|
|
})
|
|
}
|
|
}
|