Skip to content

Commit

Permalink
Register stats on app initiated user logout (#716)
Browse files Browse the repository at this point in the history
  • Loading branch information
keliramu authored Dec 16, 2024
2 parents ad82bc3 + 478b775 commit b000749
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 64 deletions.
18 changes: 13 additions & 5 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type RenewingChecker struct {
creds core.CredentialsAPI
expChecker expirationChecker
mfaPub events.Publisher[bool]
logoutPub events.Publisher[events.DataAuthorization]
errPub events.Publisher[error]
mu sync.Mutex
accountUpdateEvents *daemonevents.AccountUpdateEvents
Expand All @@ -78,6 +79,7 @@ type RenewingChecker struct {
func NewRenewingChecker(cm config.Manager,
creds core.CredentialsAPI,
mfaPub events.Publisher[bool],
logoutPub events.Publisher[events.DataAuthorization],
errPub events.Publisher[error],
accountUpdateEvents *daemonevents.AccountUpdateEvents,
) *RenewingChecker {
Expand All @@ -86,6 +88,7 @@ func NewRenewingChecker(cm config.Manager,
creds: creds,
expChecker: systemTimeExpirationChecker{},
mfaPub: mfaPub,
logoutPub: logoutPub,
errPub: errPub,
accountUpdateEvents: accountUpdateEvents,
}
Expand Down Expand Up @@ -204,7 +207,7 @@ func (r *RenewingChecker) renew(uid int64, data config.TokenData) error {
if errors.Is(err, core.ErrUnauthorized) ||
errors.Is(err, core.ErrNotFound) ||
errors.Is(err, core.ErrBadRequest) {
return r.cm.SaveWith(Logout(uid))
return r.cm.SaveWith(Logout(uid, r.logoutPub))
}
return nil
}
Expand All @@ -213,7 +216,7 @@ func (r *RenewingChecker) renew(uid int64, data config.TokenData) error {
if errors.Is(err, core.ErrUnauthorized) ||
errors.Is(err, core.ErrNotFound) ||
errors.Is(err, core.ErrBadRequest) {
return r.cm.SaveWith(Logout(uid))
return r.cm.SaveWith(Logout(uid, r.logoutPub))
}
return nil
}
Expand All @@ -222,7 +225,7 @@ func (r *RenewingChecker) renew(uid int64, data config.TokenData) error {
if errors.Is(err, core.ErrUnauthorized) ||
errors.Is(err, core.ErrNotFound) ||
errors.Is(err, core.ErrBadRequest) {
return r.cm.SaveWith(Logout(uid))
return r.cm.SaveWith(Logout(uid, r.logoutPub))
}
}
}
Expand All @@ -240,7 +243,7 @@ func (r *RenewingChecker) renew(uid int64, data config.TokenData) error {
if errors.Is(err, core.ErrUnauthorized) ||
errors.Is(err, core.ErrNotFound) ||
errors.Is(err, core.ErrBadRequest) {
return r.cm.SaveWith(Logout(uid))
return r.cm.SaveWith(Logout(uid, r.logoutPub))
}
}

Expand Down Expand Up @@ -401,8 +404,13 @@ func saveIdempotencyKey(userID int64, data config.TokenData) config.SaveFunc {
}

// Logout the user.
func Logout(user int64) config.SaveFunc {
func Logout(user int64, logoutPub events.Publisher[events.DataAuthorization]) config.SaveFunc {
return func(c config.Config) config.Config {
if logoutPub != nil {
// register stats instant logout with status success
logoutPub.Publish(events.DataAuthorization{
DurationMs: -1, EventTrigger: events.TriggerApp, EventStatus: events.StatusSuccess})
}
delete(c.TokensData, user)
return c
}
Expand Down
14 changes: 13 additions & 1 deletion auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ func (p *mockBoolPublisher) Publish(b bool) {
p.enabled = b
}

type mockAuthPublisher struct {
}

func (p *mockAuthPublisher) Publish(events.DataAuthorization) {
}

type mockErrPublisher struct {
err error
}
Expand All @@ -128,6 +134,7 @@ func TestIsMFAEnabled(t *testing.T) {
cm config.Manager
api core.CredentialsAPI
mfaPub events.Publisher[bool]
loutPub events.Publisher[events.DataAuthorization]
errPub events.Publisher[error]
isEnabled bool
err error
Expand All @@ -137,6 +144,7 @@ func TestIsMFAEnabled(t *testing.T) {
cm: &authConfigManager{},
api: &authAPI{mfaResp: core.MultifactorAuthStatusResponse{Status: internal.MFAEnabledStatusName}},
mfaPub: &mockBoolPublisher{},
loutPub: &mockAuthPublisher{},
errPub: &mockErrPublisher{},
isEnabled: true,
err: nil,
Expand All @@ -146,6 +154,7 @@ func TestIsMFAEnabled(t *testing.T) {
cm: &authConfigManager{},
api: &authAPI{mfaResp: core.MultifactorAuthStatusResponse{Status: "not enabled"}},
mfaPub: &mockBoolPublisher{},
loutPub: &mockAuthPublisher{},
errPub: &mockErrPublisher{},
isEnabled: false,
err: nil,
Expand All @@ -155,6 +164,7 @@ func TestIsMFAEnabled(t *testing.T) {
cm: &authConfigManager{loadErr: configError},
api: &authAPI{mfaResp: core.MultifactorAuthStatusResponse{Status: "not enabled"}},
mfaPub: &mockBoolPublisher{},
loutPub: &mockAuthPublisher{},
errPub: &mockErrPublisher{},
isEnabled: false,
err: configError,
Expand All @@ -164,6 +174,7 @@ func TestIsMFAEnabled(t *testing.T) {
cm: &authConfigManager{},
api: &authAPI{mfaResp: core.MultifactorAuthStatusResponse{Status: "not enabled"}, err: apiError},
mfaPub: &mockBoolPublisher{},
loutPub: &mockAuthPublisher{},
errPub: &mockErrPublisher{},
isEnabled: false,
err: apiError,
Expand All @@ -172,7 +183,7 @@ func TestIsMFAEnabled(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
rc := NewRenewingChecker(test.cm, test.api, test.mfaPub, test.errPub, daemonevents.NewAccountUpdateEvents())
rc := NewRenewingChecker(test.cm, test.api, test.mfaPub, test.loutPub, test.errPub, daemonevents.NewAccountUpdateEvents())
enabled, err := rc.isMFAEnabled()
assert.Equal(t, test.isEnabled, enabled)

Expand Down Expand Up @@ -252,6 +263,7 @@ func TestIsVPNExpired(t *testing.T) {
test.cm,
test.api,
&mockBoolPublisher{},
&mockAuthPublisher{},
&mockErrPublisher{},
&daemonevents.AccountUpdateEvents{SubscriptionUpdate: test.accPub},
)
Expand Down
1 change: 1 addition & 0 deletions cmd/daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ func main() {
fsystem,
defaultAPI,
daemonEvents.User.MFA,
daemonEvents.User.Logout,
errSubject,
accountUpdateEvents,
)
Expand Down
2 changes: 1 addition & 1 deletion daemon/rpc_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (r *RPC) AccountInfo(ctx context.Context, _ *pb.Empty) (*pb.AccountResponse
log.Println(internal.ErrorPrefix, "retrieving user:", err)
switch {
case errors.Is(err, core.ErrUnauthorized):
if err := r.cm.SaveWith(auth.Logout(cfg.AutoConnectData.ID)); err != nil {
if err := r.cm.SaveWith(auth.Logout(cfg.AutoConnectData.ID, r.events.User.Logout)); err != nil {
return &pb.AccountResponse{
Type: internal.CodeConfigError,
}, nil
Expand Down
2 changes: 1 addition & 1 deletion daemon/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ func selectServer(r *RPC, insights *core.Insights, cfg config.Config, tag string
log.Println(internal.ErrorPrefix, "picking servers:", err)
switch {
case errors.Is(err, core.ErrUnauthorized):
if err := r.cm.SaveWith(auth.Logout(cfg.AutoConnectData.ID)); err != nil {
if err := r.cm.SaveWith(auth.Logout(cfg.AutoConnectData.ID, r.events.User.Logout)); err != nil {
return nil, false, err
}
return nil, false, internal.ErrNotLoggedIn
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ require (
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.25.0
github.com/vishvananda/netlink v1.1.0
golang.org/x/crypto v0.26.0
golang.org/x/crypto v0.31.0
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/mod v0.17.0
golang.org/x/net v0.28.0
golang.org/x/oauth2 v0.18.0
golang.org/x/sys v0.23.0
golang.org/x/term v0.23.0
golang.org/x/text v0.17.0
golang.org/x/sys v0.28.0
golang.org/x/term v0.27.0
golang.org/x/text v0.21.0
golang.zx2c4.com/wireguard v0.0.0-20230313165553-0ad14a89f5f9
google.golang.org/api v0.169.0
google.golang.org/grpc v1.64.1
Expand Down Expand Up @@ -99,7 +99,7 @@ require (
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/appengine v1.6.8 // indirect
Expand Down
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
Expand Down Expand Up @@ -260,8 +260,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -277,18 +277,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
Loading

0 comments on commit b000749

Please sign in to comment.