Files
upstream-corteza/server/system/service/auth_credentials_test.go
upstream-mirror 7e385fc126
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:22:23 +05:00

290 lines
6.7 KiB
Go

package service
import (
"github.com/cortezaproject/corteza/server/system/types"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/bcrypt"
"strings"
"testing"
"time"
)
func Test_isValidPassword(t *testing.T) {
var (
pwdPlain = " ... plain password ... "
pwdHashedB, _ = bcrypt.GenerateFromPassword([]byte(pwdPlain), bcrypt.DefaultCost)
pwdHashed = string(pwdHashedB)
pwdUnknown = "$2a$10$8sOZxfZinxnu3bAtpkqEx.wBBwOfci6aG1szgUyxm5.BL2WiLu.ni"
)
cases := []struct {
name string
password string
cc types.CredentialSet
rval bool
}{
{
name: "empty set",
rval: false,
},
{
name: "bad pwd",
rval: false,
password: " foo ",
cc: types.CredentialSet{&types.Credential{ID: 1, Credentials: pwdHashed}},
},
{
name: "invalid credentials",
rval: false,
password: " foo ",
cc: types.CredentialSet{&types.Credential{ID: 0, Credentials: pwdHashed}},
},
{
name: "ok",
rval: true,
password: pwdPlain,
cc: types.CredentialSet{&types.Credential{ID: 1, Credentials: pwdHashed}},
},
{
name: "multipass",
rval: true,
password: pwdPlain,
cc: types.CredentialSet{
&types.Credential{ID: 0, Credentials: pwdHashed},
&types.Credential{ID: 1, Credentials: pwdUnknown},
&types.Credential{ID: 2, Credentials: pwdHashed},
&types.Credential{ID: 3, Credentials: ""},
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
var (
req = require.New(t)
rsp = findValidPassword(c.cc, c.password)
)
if c.rval {
req.NotNil(rsp)
} else {
req.Nil(rsp)
}
})
}
}
func Test_isPasswordReused(t *testing.T) {
var (
pwdPlain = " ... plain password ... "
pwdHashedB, _ = bcrypt.GenerateFromPassword([]byte(pwdPlain), bcrypt.DefaultCost)
pwdHashed = string(pwdHashedB)
pwdUnknown = "$2a$10$8sOZxfZinxnu3bAtpkqEx.wBBwOfci6aG1szgUyxm5.BL2WiLu.ni"
)
cases := []struct {
name string
password string
window time.Duration
cc types.CredentialSet
rval bool
}{
{
name: "no credentials, not reused",
rval: false,
password: pwdPlain,
cc: types.CredentialSet{},
},
{
name: "not reused",
rval: false,
password: pwdPlain,
cc: types.CredentialSet{
&types.Credential{ID: 1, Credentials: pwdUnknown},
&types.Credential{ID: 2, Credentials: ""},
},
},
{
name: "present, valid, first",
rval: true,
password: pwdPlain,
cc: types.CredentialSet{
&types.Credential{ID: 1, Credentials: pwdHashed},
&types.Credential{ID: 2, Credentials: pwdUnknown},
&types.Credential{ID: 3, Credentials: ""},
},
},
{
name: "present, but within time window",
rval: false,
password: pwdPlain,
window: 5 * time.Minute,
cc: types.CredentialSet{
&types.Credential{ID: 1, Credentials: pwdHashed, CreatedAt: *now()},
&types.Credential{ID: 2, Credentials: pwdUnknown},
&types.Credential{ID: 3, Credentials: ""},
},
},
{
name: "present, invalid, last",
rval: true,
password: pwdPlain,
cc: types.CredentialSet{
&types.Credential{ID: 2, Credentials: pwdUnknown},
&types.Credential{ID: 3, Credentials: ""},
&types.Credential{ID: 1, Credentials: pwdHashed, DeletedAt: now()},
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
var (
req = require.New(t)
rsp = isPasswordReused(c.cc, c.password, c.window)
)
if c.rval {
req.True(rsp)
} else {
req.False(rsp)
}
})
}
}
func TestValidateToken(t *testing.T) {
type args struct {
token string
}
tests := []struct {
name string
args args
wantID uint64
wantCredentials string
}{
{
name: "empty",
wantID: 0,
wantCredentials: "",
args: args{token: ""}},
{
name: "foo",
wantID: 0,
wantCredentials: "",
args: args{token: "foo1"}},
{
name: "semivalid",
wantID: 0,
wantCredentials: "",
args: args{token: "foofoofoofoofoofoofoofoofoofoofo0"}},
{
name: "valid",
wantID: 1,
wantCredentials: "foofoofoofoofoofoofoofoofoofoofo",
args: args{token: "foofoofoofoofoofoofoofoofoofoofo1"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotID, gotCredentials := validateToken(tt.args.token)
if gotID != tt.wantID {
t.Errorf("auth.validateToken() gotID = %v, want %v", gotID, tt.wantID)
}
if gotCredentials != tt.wantCredentials {
t.Errorf("auth.validateToken() gotCredentials = %v, want %v", gotCredentials, tt.wantCredentials)
}
})
}
}
func Test_checkPasswordStrength(t *testing.T) {
tests := []struct {
name string
pc types.PasswordConstraints
password string
want bool
}{
{
name: "empty",
pc: types.PasswordConstraints{},
password: "",
want: false,
},
{
name: "sys too short",
pc: types.PasswordConstraints{},
password: strings.Repeat("A", passwordMinLength-1),
want: false,
},
{
name: "sys too long",
pc: types.PasswordConstraints{},
password: strings.Repeat("A", passwordMaxLength+1),
want: false,
},
{
name: "too short",
pc: types.PasswordConstraints{MinLength: 10},
password: "123456789",
want: false,
},
{
name: "uc valid",
pc: types.PasswordConstraints{MinUpperCase: 2},
password: "aaaAAAaaa",
want: true,
},
{
name: "uc invalid",
pc: types.PasswordConstraints{MinUpperCase: 2},
password: "aaaaaaaa",
want: false,
},
{
name: "lc valid",
pc: types.PasswordConstraints{MinLowerCase: 2},
password: "AAAaaAAAA",
want: true,
},
{
name: "lc invalid",
pc: types.PasswordConstraints{MinLowerCase: 2},
password: "AAAAAAAAA",
want: false,
},
{
name: "digit valid",
pc: types.PasswordConstraints{MinNumCount: 2},
password: "AAA12AAAA",
want: true,
},
{
name: "digit invalid",
pc: types.PasswordConstraints{MinNumCount: 2},
password: "AAAaaAAAA",
want: false,
},
{
name: "special valid",
pc: types.PasswordConstraints{MinSpecialCount: 2},
password: "AAA!!AAAA",
want: true,
},
{
name: "special invalid",
pc: types.PasswordConstraints{MinSpecialCount: 2},
password: "AAAaaAAAA",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.pc.PasswordSecurity = true
if got := checkPasswordStrength(tt.password, tt.pc); got != tt.want {
t.Errorf("checkPasswordStrength() = %v, want %v", got, tt.want)
}
})
}
}