mirror of
https://github.com/netbirdio/netbird.git
synced 2025-01-24 23:08:55 +01:00
Fix tests
Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com>
This commit is contained in:
parent
7e3ff3044c
commit
c76683a8d3
2
go.mod
2
go.mod
@ -39,6 +39,7 @@ require (
|
||||
github.com/coreos/go-iptables v0.7.0
|
||||
github.com/creack/pty v1.1.18
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/docker/docker v26.1.5+incompatible
|
||||
github.com/eko/gocache/v3 v3.1.1
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gliderlabs/ssh v0.3.4
|
||||
@ -140,7 +141,6 @@ require (
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/docker v26.1.5+incompatible // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
|
@ -3,7 +3,6 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
b64 "encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@ -17,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
|
||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
@ -188,7 +188,7 @@ func TestAccount_GetPeerNetworkMap(t *testing.T) {
|
||||
LoginExpired: true,
|
||||
},
|
||||
UserID: userID,
|
||||
LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-time.Hour * 24 * 30 * 30)),
|
||||
},
|
||||
"peer-2": {
|
||||
ID: peerID2,
|
||||
@ -202,7 +202,7 @@ func TestAccount_GetPeerNetworkMap(t *testing.T) {
|
||||
LoginExpired: false,
|
||||
},
|
||||
UserID: userID,
|
||||
LastLogin: time.Now().UTC(),
|
||||
LastLogin: util.ToPtr(time.Now().UTC()),
|
||||
LoginExpirationEnabled: true,
|
||||
},
|
||||
},
|
||||
@ -226,7 +226,7 @@ func TestAccount_GetPeerNetworkMap(t *testing.T) {
|
||||
LoginExpired: true,
|
||||
},
|
||||
UserID: userID,
|
||||
LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-time.Hour * 24 * 30 * 30)),
|
||||
LoginExpirationEnabled: true,
|
||||
},
|
||||
"peer-2": {
|
||||
@ -241,7 +241,7 @@ func TestAccount_GetPeerNetworkMap(t *testing.T) {
|
||||
LoginExpired: true,
|
||||
},
|
||||
UserID: userID,
|
||||
LastLogin: time.Now().UTC().Add(-time.Hour * 24 * 30 * 30),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-time.Hour * 24 * 30 * 30)),
|
||||
LoginExpirationEnabled: true,
|
||||
},
|
||||
},
|
||||
@ -814,7 +814,6 @@ func TestDefaultAccountManager_MarkPATUsed(t *testing.T) {
|
||||
"tokenId": {
|
||||
ID: "tokenId",
|
||||
HashedToken: encodedHashedToken,
|
||||
LastUsed: time.Time{},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -1097,7 +1096,7 @@ func genUsers(p string, n int) map[string]*types.User {
|
||||
users[fmt.Sprintf("%s-%d", p, i)] = &types.User{
|
||||
Id: fmt.Sprintf("%s-%d", p, i),
|
||||
Role: types.UserRoleAdmin,
|
||||
LastLogin: sql.NullTime{Time: now, Valid: !now.IsZero()},
|
||||
LastLogin: util.ToPtr(now),
|
||||
CreatedAt: now,
|
||||
Issued: "api",
|
||||
AutoGroups: []string{"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"},
|
||||
@ -1749,10 +1748,10 @@ func TestAccount_Copy(t *testing.T) {
|
||||
ID: "pat1",
|
||||
Name: "First PAT",
|
||||
HashedToken: "SoMeHaShEdToKeN",
|
||||
ExpirationDate: time.Now().UTC().AddDate(0, 0, 7),
|
||||
ExpirationDate: util.ToPtr(time.Now().UTC().AddDate(0, 0, 7)),
|
||||
CreatedBy: "user1",
|
||||
CreatedAt: time.Now().UTC(),
|
||||
LastUsed: time.Now().UTC(),
|
||||
LastUsed: util.ToPtr(time.Now().UTC()),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -2108,7 +2107,7 @@ func TestAccount_GetExpiredPeers(t *testing.T) {
|
||||
Connected: true,
|
||||
LoginExpired: false,
|
||||
},
|
||||
LastLogin: time.Now().UTC().Add(-30 * time.Minute),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-30 * time.Minute)),
|
||||
UserID: userID,
|
||||
},
|
||||
"peer-2": {
|
||||
@ -2119,7 +2118,7 @@ func TestAccount_GetExpiredPeers(t *testing.T) {
|
||||
Connected: true,
|
||||
LoginExpired: false,
|
||||
},
|
||||
LastLogin: time.Now().UTC().Add(-2 * time.Hour),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-2 * time.Hour)),
|
||||
UserID: userID,
|
||||
},
|
||||
|
||||
@ -2131,7 +2130,7 @@ func TestAccount_GetExpiredPeers(t *testing.T) {
|
||||
Connected: true,
|
||||
LoginExpired: false,
|
||||
},
|
||||
LastLogin: time.Now().UTC().Add(-1 * time.Hour),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-1 * time.Hour)),
|
||||
UserID: userID,
|
||||
},
|
||||
},
|
||||
@ -2193,7 +2192,7 @@ func TestAccount_GetInactivePeers(t *testing.T) {
|
||||
Connected: false,
|
||||
LoginExpired: false,
|
||||
},
|
||||
LastLogin: time.Now().UTC().Add(-30 * time.Minute),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-30 * time.Minute)),
|
||||
UserID: userID,
|
||||
},
|
||||
"peer-2": {
|
||||
@ -2204,7 +2203,7 @@ func TestAccount_GetInactivePeers(t *testing.T) {
|
||||
Connected: false,
|
||||
LoginExpired: false,
|
||||
},
|
||||
LastLogin: time.Now().UTC().Add(-2 * time.Hour),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-2 * time.Hour)),
|
||||
UserID: userID,
|
||||
},
|
||||
"peer-3": {
|
||||
@ -2215,7 +2214,7 @@ func TestAccount_GetInactivePeers(t *testing.T) {
|
||||
Connected: true,
|
||||
LoginExpired: false,
|
||||
},
|
||||
LastLogin: time.Now().UTC().Add(-1 * time.Hour),
|
||||
LastLogin: util.ToPtr(time.Now().UTC().Add(-1 * time.Hour)),
|
||||
UserID: userID,
|
||||
},
|
||||
},
|
||||
@ -2485,7 +2484,7 @@ func TestAccount_GetNextPeerExpiration(t *testing.T) {
|
||||
LoginExpired: false,
|
||||
},
|
||||
LoginExpirationEnabled: true,
|
||||
LastLogin: time.Now().UTC(),
|
||||
LastLogin: util.ToPtr(time.Now().UTC()),
|
||||
UserID: userID,
|
||||
},
|
||||
"peer-2": {
|
||||
@ -2645,7 +2644,7 @@ func TestAccount_GetNextInactivePeerExpiration(t *testing.T) {
|
||||
LastSeen: time.Now().Add(-1 * time.Second),
|
||||
},
|
||||
InactivityExpirationEnabled: true,
|
||||
LastLogin: time.Now().UTC(),
|
||||
LastLogin: util.ToPtr(time.Now().UTC()),
|
||||
UserID: userID,
|
||||
},
|
||||
"peer-2": {
|
||||
@ -2723,8 +2722,8 @@ func TestAccount_SetJWTGroups(t *testing.T) {
|
||||
},
|
||||
Settings: &types.Settings{GroupsPropagationEnabled: true, JWTGroupsEnabled: true, JWTGroupsClaimName: "groups"},
|
||||
Users: map[string]*types.User{
|
||||
"user1": {Id: "user1", AccountID: "accountID"},
|
||||
"user2": {Id: "user2", AccountID: "accountID"},
|
||||
"user1": {Id: "user1", AccountID: "accountID", CreatedAt: time.Now()},
|
||||
"user2": {Id: "user2", AccountID: "accountID", CreatedAt: time.Now()},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -355,6 +355,7 @@ func initTestGroupAccount(am *DefaultAccountManager) (*DefaultAccountManager, *t
|
||||
setupKey := &types.SetupKey{
|
||||
Id: "example setup key",
|
||||
AutoGroups: []string{groupForSetupKeys.ID},
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
user := &types.User{
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
@ -239,7 +240,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: toPtr("192.168.0.0/16"),
|
||||
Network: util.ToPtr("192.168.0.0/16"),
|
||||
Peer: &existingPeerID,
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
@ -259,7 +260,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
NetworkId: "domainNet",
|
||||
Network: toPtr("invalid Prefix"),
|
||||
Network: util.ToPtr("invalid Prefix"),
|
||||
KeepRoute: true,
|
||||
Domains: &[]string{existingDomain},
|
||||
Peer: &existingPeerID,
|
||||
@ -281,7 +282,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: toPtr("192.168.0.0/16"),
|
||||
Network: util.ToPtr("192.168.0.0/16"),
|
||||
Peer: &existingPeerID,
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
@ -385,7 +386,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: toPtr("192.168.0.0/16"),
|
||||
Network: util.ToPtr("192.168.0.0/16"),
|
||||
Peer: &existingPeerID,
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
@ -404,7 +405,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: toPtr("invalid Prefix"),
|
||||
Network: util.ToPtr("invalid Prefix"),
|
||||
Domains: &[]string{existingDomain},
|
||||
Peer: &existingPeerID,
|
||||
NetworkType: route.DomainNetworkString,
|
||||
@ -425,7 +426,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: toPtr("192.168.0.0/16"),
|
||||
Network: util.ToPtr("192.168.0.0/16"),
|
||||
Peer: &emptyString,
|
||||
PeerGroups: &[]string{existingGroupID},
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
@ -663,7 +664,3 @@ func toApiRoute(t *testing.T, r *route.Route) *api.Route {
|
||||
require.NoError(t, err, "Failed to convert route")
|
||||
return apiRoute
|
||||
}
|
||||
|
||||
func toPtr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func toResponseBody(key *types.SetupKey) *api.SetupKey {
|
||||
Id: key.Id,
|
||||
Key: key.KeySecret,
|
||||
Name: key.Name,
|
||||
Expires: key.ExpiresAt,
|
||||
Expires: key.ExpirationTime(),
|
||||
Type: string(key.Type),
|
||||
Valid: key.IsValid(),
|
||||
Revoked: key.Revoked,
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
@ -42,19 +43,19 @@ var testAccount = &types.Account{
|
||||
ID: existingTokenID,
|
||||
Name: "My first token",
|
||||
HashedToken: "someHash",
|
||||
ExpirationDate: time.Now().UTC().AddDate(0, 0, 7),
|
||||
ExpirationDate: util.ToPtr(time.Now().UTC().AddDate(0, 0, 7)),
|
||||
CreatedBy: existingUserID,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
LastUsed: time.Now().UTC(),
|
||||
LastUsed: util.ToPtr(time.Now().UTC()),
|
||||
},
|
||||
"token2": {
|
||||
ID: "token2",
|
||||
Name: "My second token",
|
||||
HashedToken: "someOtherHash",
|
||||
ExpirationDate: time.Now().UTC().AddDate(0, 0, 7),
|
||||
ExpirationDate: util.ToPtr(time.Now().UTC().AddDate(0, 0, 7)),
|
||||
CreatedBy: existingUserID,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
LastUsed: time.Now().UTC(),
|
||||
LastUsed: util.ToPtr(time.Now().UTC()),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -248,8 +249,8 @@ func toTokenResponse(serverToken types.PersonalAccessToken) api.PersonalAccessTo
|
||||
Id: serverToken.ID,
|
||||
Name: serverToken.Name,
|
||||
CreatedAt: serverToken.CreatedAt,
|
||||
LastUsed: &serverToken.LastUsed,
|
||||
LastUsed: serverToken.LastUsed,
|
||||
CreatedBy: serverToken.CreatedBy,
|
||||
ExpirationDate: serverToken.ExpirationDate,
|
||||
ExpirationDate: serverToken.ExpirationTime(),
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/http/middleware/bypass"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
@ -39,10 +40,10 @@ var testAccount = &types.Account{
|
||||
ID: tokenID,
|
||||
Name: "My first token",
|
||||
HashedToken: "someHash",
|
||||
ExpirationDate: time.Now().UTC().AddDate(0, 0, 7),
|
||||
ExpirationDate: util.ToPtr(time.Now().UTC().AddDate(0, 0, 7)),
|
||||
CreatedBy: userID,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
LastUsed: time.Now().UTC(),
|
||||
LastUsed: util.ToPtr(time.Now().UTC()),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
"github.com/rs/xid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -80,7 +81,7 @@ func TestPeer_LoginExpired(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
peer := &nbpeer.Peer{
|
||||
LoginExpirationEnabled: c.expirationEnabled,
|
||||
LastLogin: c.lastLogin,
|
||||
LastLogin: util.ToPtr(c.lastLogin),
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
@ -141,7 +142,7 @@ func TestPeer_SessionExpired(t *testing.T) {
|
||||
}
|
||||
peer := &nbpeer.Peer{
|
||||
InactivityExpirationEnabled: c.expirationEnabled,
|
||||
LastLogin: c.lastLogin,
|
||||
LastLogin: util.ToPtr(c.lastLogin),
|
||||
Status: peerStatus,
|
||||
UserID: userID,
|
||||
}
|
||||
@ -1209,7 +1210,7 @@ func Test_RegisterPeerByUser(t *testing.T) {
|
||||
UserID: existingUserID,
|
||||
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()},
|
||||
SSHEnabled: false,
|
||||
LastLogin: time.Now(),
|
||||
LastLogin: util.ToPtr(time.Now()),
|
||||
}
|
||||
|
||||
addedPeer, _, _, err := am.AddPeer(context.Background(), "", existingUserID, newPeer)
|
||||
|
@ -66,7 +66,7 @@ func TestDefaultAccountManager_SaveSetupKey(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertKey(t, newKey, keyName, revoked, "reusable", 0, key.CreatedAt, key.ExpiresAt,
|
||||
assertKey(t, newKey, keyName, revoked, "reusable", 0, key.CreatedAt, key.ExpirationTime(),
|
||||
key.Id, time.Now().UTC(), autoGroups, true)
|
||||
|
||||
// check the corresponding events that should have been generated
|
||||
@ -391,7 +391,7 @@ func TestSetupKey_Copy(t *testing.T) {
|
||||
key, _ := types.GenerateSetupKey("key name", types.SetupKeyOneOff, time.Hour, []string{}, types.SetupKeyUnlimitedUsage, false)
|
||||
keyCopy := key.Copy()
|
||||
|
||||
assertKey(t, keyCopy, key.Name, key.Revoked, string(key.Type), key.UsedTimes, key.CreatedAt, key.ExpiresAt, key.Id,
|
||||
assertKey(t, keyCopy, key.Name, key.Revoked, string(key.Type), key.UsedTimes, key.CreatedAt, key.ExpirationTime(), key.Id,
|
||||
key.UpdatedAt, key.AutoGroups, true)
|
||||
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ type SetupKey struct {
|
||||
Name string
|
||||
Type SetupKeyType
|
||||
CreatedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
ExpiresAt *time.Time
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime:false"`
|
||||
// Revoked indicates whether the key was revoked or not (we don't remove them for tracking purposes)
|
||||
Revoked bool
|
||||
@ -95,6 +95,14 @@ func (key *SetupKey) LastUsedTime() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// ExpirationTime returns the expiration time of the setup key.
|
||||
func (key *SetupKey) ExpirationTime() time.Time {
|
||||
if key.ExpiresAt != nil {
|
||||
return *key.ExpiresAt
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// HiddenKey returns the Key value hidden with "*" and a 5 character prefix.
|
||||
// E.g., "831F6*******************************"
|
||||
func HiddenKey(key string, length int) string {
|
||||
@ -125,10 +133,10 @@ func (key *SetupKey) IsRevoked() bool {
|
||||
|
||||
// IsExpired if key was expired
|
||||
func (key *SetupKey) IsExpired() bool {
|
||||
if key.ExpiresAt.IsZero() {
|
||||
if key.ExpirationTime().IsZero() {
|
||||
return false
|
||||
}
|
||||
return time.Now().After(key.ExpiresAt)
|
||||
return time.Now().After(key.ExpirationTime())
|
||||
}
|
||||
|
||||
// IsOverUsed if the key was used too many times. SetupKey.UsageLimit == 0 indicates the unlimited usage.
|
||||
@ -149,9 +157,9 @@ func GenerateSetupKey(name string, t SetupKeyType, validFor time.Duration, autoG
|
||||
limit = 1
|
||||
}
|
||||
|
||||
expiresAt := time.Time{}
|
||||
var expiresAt *time.Time
|
||||
if validFor != 0 {
|
||||
expiresAt = time.Now().UTC().Add(validFor)
|
||||
expiresAt = util.ToPtr(time.Now().UTC().Add(validFor))
|
||||
}
|
||||
|
||||
hashedKey := sha256.Sum256([]byte(key))
|
||||
|
@ -2,7 +2,6 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
@ -11,6 +10,7 @@ import (
|
||||
"github.com/eko/gocache/v3/cache"
|
||||
cacheStore "github.com/eko/gocache/v3/store"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
@ -322,14 +322,14 @@ func TestUser_Copy(t *testing.T) {
|
||||
ID: "pat1",
|
||||
Name: "First PAT",
|
||||
HashedToken: "SoMeHaShEdToKeN",
|
||||
ExpirationDate: time.Now().AddDate(0, 0, 7),
|
||||
ExpirationDate: util.ToPtr(time.Now().AddDate(0, 0, 7)),
|
||||
CreatedBy: "userId",
|
||||
CreatedAt: time.Now(),
|
||||
LastUsed: time.Now(),
|
||||
LastUsed: util.ToPtr(time.Now()),
|
||||
},
|
||||
},
|
||||
Blocked: false,
|
||||
LastLogin: sql.NullTime{Time: time.Now().UTC(), Valid: true},
|
||||
LastLogin: util.ToPtr(time.Now().UTC()),
|
||||
CreatedAt: time.Now().UTC(),
|
||||
Issued: "test",
|
||||
IntegrationReference: integration_reference.IntegrationReference{
|
||||
|
Loading…
Reference in New Issue
Block a user