From e8591537e0b521b286d6acafef4c03d1747712d8 Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Tue, 16 Nov 2021 15:08:20 +0100 Subject: [PATCH] [MM-39851] Add CRUD methods for user sessions to plugin API (#18958) --- app/plugin_api.go | 26 +++-- app/session.go | 8 ++ i18n/en.json | 4 + plugin/api.go | 29 +++++- plugin/api_timer_layer_generated.go | 35 +++++-- plugin/client_rpc_generated.go | 144 ++++++++++++++++++++++------ plugin/plugintest/api.go | 57 +++++++++++ 7 files changed, 252 insertions(+), 51 deletions(-) diff --git a/app/plugin_api.go b/app/plugin_api.go index 92403aa8b3..845911b47f 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -90,16 +90,6 @@ func (api *PluginAPI) ExecuteSlashCommand(commandArgs *model.CommandArgs) (*mode return response, nil } -func (api *PluginAPI) GetSession(sessionID string) (*model.Session, *model.AppError) { - session, err := api.app.GetSessionById(sessionID) - - if err != nil { - return nil, err - } - - return session, nil -} - func (api *PluginAPI) GetConfig() *model.Config { return api.app.GetSanitizedConfig() } @@ -290,6 +280,22 @@ func (api *PluginAPI) DeletePreferencesForUser(userID string, preferences []mode return api.app.DeletePreferences(userID, preferences) } +func (api *PluginAPI) GetSession(sessionID string) (*model.Session, *model.AppError) { + return api.app.GetSessionById(sessionID) +} + +func (api *PluginAPI) CreateSession(session *model.Session) (*model.Session, *model.AppError) { + return api.app.CreateSession(session) +} + +func (api *PluginAPI) ExtendSessionExpiry(sessionID string, expiresAt int64) *model.AppError { + return api.app.extendSessionExpiry(sessionID, expiresAt) +} + +func (api *PluginAPI) RevokeSession(sessionID string) *model.AppError { + return api.app.RevokeSessionById(sessionID) +} + func (api *PluginAPI) CreateUserAccessToken(token *model.UserAccessToken) (*model.UserAccessToken, *model.AppError) { return api.app.CreateUserAccessToken(token) } diff --git a/app/session.go b/app/session.go index 89d42b7769..2029fd0414 100644 --- a/app/session.go +++ b/app/session.go @@ -306,6 +306,14 @@ func (a *App) ExtendSessionExpiryIfNeeded(session *model.Session) bool { return true } +func (a *App) extendSessionExpiry(sessionID string, newExpiry int64) *model.AppError { + if err := a.Srv().Store.Session().UpdateExpiresAt(sessionID, newExpiry); err != nil { + return model.NewAppError("ExtendSessionExpiry", "app.session.extend_session_expiry.app_error", nil, err.Error(), http.StatusInternalServerError) + } + + return nil +} + // GetSessionLengthInMillis returns the session length, in milliseconds, // based on the type of session (Mobile, SSO, Web/LDAP). func (a *App) GetSessionLengthInMillis(session *model.Session) int64 { diff --git a/i18n/en.json b/i18n/en.json index d4f82286fc..65afc7923b 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -5983,6 +5983,10 @@ "id": "app.session.analytics_session_count.app_error", "translation": "Unable to count the sessions." }, + { + "id": "app.session.extend_session_expiry.app_error", + "translation": "Unable to extend session length" + }, { "id": "app.session.get.app_error", "translation": "We encountered an error finding the session." diff --git a/plugin/api.go b/plugin/api.go index 0f70ab566f..cd48b76835 100644 --- a/plugin/api.go +++ b/plugin/api.go @@ -44,11 +44,6 @@ type API interface { // Minimum server version: 5.26 ExecuteSlashCommand(commandArgs *model.CommandArgs) (*model.CommandResponse, error) - // GetSession returns the session object for the Session ID - // - // Minimum server version: 5.2 - GetSession(sessionID string) (*model.Session, *model.AppError) - // GetConfig fetches the currently persisted config // // @tag Configuration @@ -192,6 +187,30 @@ type API interface { // Minimum server version: 5.26 DeletePreferencesForUser(userID string, preferences []model.Preference) *model.AppError + // GetSession returns the session object for the Session ID + // + // + // Minimum server version: 5.2 + GetSession(sessionID string) (*model.Session, *model.AppError) + + // CreateSession creates a new user session. + // + // @tag User + // Minimum server version: 6.2 + CreateSession(session *model.Session) (*model.Session, *model.AppError) + + // ExtendSessionExpiry extends the duration of an existing session. + // + // @tag User + // Minimum server version: 6.2 + ExtendSessionExpiry(sessionID string, newExpiry int64) *model.AppError + + // RevokeSession revokes an existing user session. + // + // @tag User + // Minimum server version: 6.2 + RevokeSession(sessionID string) *model.AppError + // CreateUserAccessToken creates a new access token. // @tag User // Minimum server version: 5.38 diff --git a/plugin/api_timer_layer_generated.go b/plugin/api_timer_layer_generated.go index 111c059261..67fc99634d 100644 --- a/plugin/api_timer_layer_generated.go +++ b/plugin/api_timer_layer_generated.go @@ -56,13 +56,6 @@ func (api *apiTimerLayer) ExecuteSlashCommand(commandArgs *model.CommandArgs) (* return _returnsA, _returnsB } -func (api *apiTimerLayer) GetSession(sessionID string) (*model.Session, *model.AppError) { - startTime := timePkg.Now() - _returnsA, _returnsB := api.apiImpl.GetSession(sessionID) - api.recordTime(startTime, "GetSession", _returnsB == nil) - return _returnsA, _returnsB -} - func (api *apiTimerLayer) GetConfig() *model.Config { startTime := timePkg.Now() _returnsA := api.apiImpl.GetConfig() @@ -224,6 +217,34 @@ func (api *apiTimerLayer) DeletePreferencesForUser(userID string, preferences [] return _returnsA } +func (api *apiTimerLayer) GetSession(sessionID string) (*model.Session, *model.AppError) { + startTime := timePkg.Now() + _returnsA, _returnsB := api.apiImpl.GetSession(sessionID) + api.recordTime(startTime, "GetSession", _returnsB == nil) + return _returnsA, _returnsB +} + +func (api *apiTimerLayer) CreateSession(session *model.Session) (*model.Session, *model.AppError) { + startTime := timePkg.Now() + _returnsA, _returnsB := api.apiImpl.CreateSession(session) + api.recordTime(startTime, "CreateSession", _returnsB == nil) + return _returnsA, _returnsB +} + +func (api *apiTimerLayer) ExtendSessionExpiry(sessionID string, newExpiry int64) *model.AppError { + startTime := timePkg.Now() + _returnsA := api.apiImpl.ExtendSessionExpiry(sessionID, newExpiry) + api.recordTime(startTime, "ExtendSessionExpiry", _returnsA == nil) + return _returnsA +} + +func (api *apiTimerLayer) RevokeSession(sessionID string) *model.AppError { + startTime := timePkg.Now() + _returnsA := api.apiImpl.RevokeSession(sessionID) + api.recordTime(startTime, "RevokeSession", _returnsA == nil) + return _returnsA +} + func (api *apiTimerLayer) CreateUserAccessToken(token *model.UserAccessToken) (*model.UserAccessToken, *model.AppError) { startTime := timePkg.Now() _returnsA, _returnsB := api.apiImpl.CreateUserAccessToken(token) diff --git a/plugin/client_rpc_generated.go b/plugin/client_rpc_generated.go index 06914133c6..8ee7b6c89c 100644 --- a/plugin/client_rpc_generated.go +++ b/plugin/client_rpc_generated.go @@ -758,35 +758,6 @@ func (s *apiRPCServer) ExecuteSlashCommand(args *Z_ExecuteSlashCommandArgs, retu return nil } -type Z_GetSessionArgs struct { - A string -} - -type Z_GetSessionReturns struct { - A *model.Session - B *model.AppError -} - -func (g *apiRPCClient) GetSession(sessionID string) (*model.Session, *model.AppError) { - _args := &Z_GetSessionArgs{sessionID} - _returns := &Z_GetSessionReturns{} - if err := g.client.Call("Plugin.GetSession", _args, _returns); err != nil { - log.Printf("RPC call to GetSession API failed: %s", err.Error()) - } - return _returns.A, _returns.B -} - -func (s *apiRPCServer) GetSession(args *Z_GetSessionArgs, returns *Z_GetSessionReturns) error { - if hook, ok := s.impl.(interface { - GetSession(sessionID string) (*model.Session, *model.AppError) - }); ok { - returns.A, returns.B = hook.GetSession(args.A) - } else { - return encodableError(fmt.Errorf("API GetSession called but not implemented.")) - } - return nil -} - type Z_GetConfigArgs struct { } @@ -1436,6 +1407,121 @@ func (s *apiRPCServer) DeletePreferencesForUser(args *Z_DeletePreferencesForUser return nil } +type Z_GetSessionArgs struct { + A string +} + +type Z_GetSessionReturns struct { + A *model.Session + B *model.AppError +} + +func (g *apiRPCClient) GetSession(sessionID string) (*model.Session, *model.AppError) { + _args := &Z_GetSessionArgs{sessionID} + _returns := &Z_GetSessionReturns{} + if err := g.client.Call("Plugin.GetSession", _args, _returns); err != nil { + log.Printf("RPC call to GetSession API failed: %s", err.Error()) + } + return _returns.A, _returns.B +} + +func (s *apiRPCServer) GetSession(args *Z_GetSessionArgs, returns *Z_GetSessionReturns) error { + if hook, ok := s.impl.(interface { + GetSession(sessionID string) (*model.Session, *model.AppError) + }); ok { + returns.A, returns.B = hook.GetSession(args.A) + } else { + return encodableError(fmt.Errorf("API GetSession called but not implemented.")) + } + return nil +} + +type Z_CreateSessionArgs struct { + A *model.Session +} + +type Z_CreateSessionReturns struct { + A *model.Session + B *model.AppError +} + +func (g *apiRPCClient) CreateSession(session *model.Session) (*model.Session, *model.AppError) { + _args := &Z_CreateSessionArgs{session} + _returns := &Z_CreateSessionReturns{} + if err := g.client.Call("Plugin.CreateSession", _args, _returns); err != nil { + log.Printf("RPC call to CreateSession API failed: %s", err.Error()) + } + return _returns.A, _returns.B +} + +func (s *apiRPCServer) CreateSession(args *Z_CreateSessionArgs, returns *Z_CreateSessionReturns) error { + if hook, ok := s.impl.(interface { + CreateSession(session *model.Session) (*model.Session, *model.AppError) + }); ok { + returns.A, returns.B = hook.CreateSession(args.A) + } else { + return encodableError(fmt.Errorf("API CreateSession called but not implemented.")) + } + return nil +} + +type Z_ExtendSessionExpiryArgs struct { + A string + B int64 +} + +type Z_ExtendSessionExpiryReturns struct { + A *model.AppError +} + +func (g *apiRPCClient) ExtendSessionExpiry(sessionID string, newExpiry int64) *model.AppError { + _args := &Z_ExtendSessionExpiryArgs{sessionID, newExpiry} + _returns := &Z_ExtendSessionExpiryReturns{} + if err := g.client.Call("Plugin.ExtendSessionExpiry", _args, _returns); err != nil { + log.Printf("RPC call to ExtendSessionExpiry API failed: %s", err.Error()) + } + return _returns.A +} + +func (s *apiRPCServer) ExtendSessionExpiry(args *Z_ExtendSessionExpiryArgs, returns *Z_ExtendSessionExpiryReturns) error { + if hook, ok := s.impl.(interface { + ExtendSessionExpiry(sessionID string, newExpiry int64) *model.AppError + }); ok { + returns.A = hook.ExtendSessionExpiry(args.A, args.B) + } else { + return encodableError(fmt.Errorf("API ExtendSessionExpiry called but not implemented.")) + } + return nil +} + +type Z_RevokeSessionArgs struct { + A string +} + +type Z_RevokeSessionReturns struct { + A *model.AppError +} + +func (g *apiRPCClient) RevokeSession(sessionID string) *model.AppError { + _args := &Z_RevokeSessionArgs{sessionID} + _returns := &Z_RevokeSessionReturns{} + if err := g.client.Call("Plugin.RevokeSession", _args, _returns); err != nil { + log.Printf("RPC call to RevokeSession API failed: %s", err.Error()) + } + return _returns.A +} + +func (s *apiRPCServer) RevokeSession(args *Z_RevokeSessionArgs, returns *Z_RevokeSessionReturns) error { + if hook, ok := s.impl.(interface { + RevokeSession(sessionID string) *model.AppError + }); ok { + returns.A = hook.RevokeSession(args.A) + } else { + return encodableError(fmt.Errorf("API RevokeSession called but not implemented.")) + } + return nil +} + type Z_CreateUserAccessTokenArgs struct { A *model.UserAccessToken } diff --git a/plugin/plugintest/api.go b/plugin/plugintest/api.go index 57229c23a0..5345ea0413 100644 --- a/plugin/plugintest/api.go +++ b/plugin/plugintest/api.go @@ -266,6 +266,31 @@ func (_m *API) CreatePost(post *model.Post) (*model.Post, *model.AppError) { return r0, r1 } +// CreateSession provides a mock function with given fields: session +func (_m *API) CreateSession(session *model.Session) (*model.Session, *model.AppError) { + ret := _m.Called(session) + + var r0 *model.Session + if rf, ok := ret.Get(0).(func(*model.Session) *model.Session); ok { + r0 = rf(session) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Session) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Session) *model.AppError); ok { + r1 = rf(session) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + // CreateTeam provides a mock function with given fields: team func (_m *API) CreateTeam(team *model.Team) (*model.Team, *model.AppError) { ret := _m.Called(team) @@ -618,6 +643,22 @@ func (_m *API) ExecuteSlashCommand(commandArgs *model.CommandArgs) (*model.Comma return r0, r1 } +// ExtendSessionExpiry provides a mock function with given fields: sessionID, newExpiry +func (_m *API) ExtendSessionExpiry(sessionID string, newExpiry int64) *model.AppError { + ret := _m.Called(sessionID, newExpiry) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string, int64) *model.AppError); ok { + r0 = rf(sessionID, newExpiry) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + // GetBot provides a mock function with given fields: botUserId, includeDeleted func (_m *API) GetBot(botUserId string, includeDeleted bool) (*model.Bot, *model.AppError) { ret := _m.Called(botUserId, includeDeleted) @@ -2950,6 +2991,22 @@ func (_m *API) RequestTrialLicense(requesterID string, users int, termsAccepted return r0 } +// RevokeSession provides a mock function with given fields: sessionID +func (_m *API) RevokeSession(sessionID string) *model.AppError { + ret := _m.Called(sessionID) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { + r0 = rf(sessionID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + // RevokeUserAccessToken provides a mock function with given fields: tokenID func (_m *API) RevokeUserAccessToken(tokenID string) *model.AppError { ret := _m.Called(tokenID)