1
0
mirror of https://github.com/mattermost/focalboard.git synced 2025-01-26 18:48:15 +02:00

Adding explict logout logic (#1895)

* Adding explict logout logic

* Fixing golangci-lint errors
This commit is contained in:
Jesús Espino 2021-12-01 10:21:31 +01:00 committed by GitHub
parent f450555439
commit 2f08c67827
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 86 additions and 4 deletions

View File

@ -89,6 +89,7 @@ func (a *API) RegisterRoutes(r *mux.Router) {
apiv1.HandleFunc("/users/{userID}/changepassword", a.sessionRequired(a.handleChangePassword)).Methods("POST")
apiv1.HandleFunc("/login", a.handleLogin).Methods("POST")
apiv1.HandleFunc("/logout", a.sessionRequired(a.handleLogout)).Methods("POST")
apiv1.HandleFunc("/register", a.handleRegister).Methods("POST")
apiv1.HandleFunc("/clientConfig", a.getClientConfig).Methods("GET")

View File

@ -211,6 +211,49 @@ func (a *API) handleLogin(w http.ResponseWriter, r *http.Request) {
a.errorResponse(w, r.URL.Path, http.StatusBadRequest, "invalid login type", nil)
}
func (a *API) handleLogout(w http.ResponseWriter, r *http.Request) {
// swagger:operation POST /api/v1/logout logout
//
// Logout user
//
// ---
// produces:
// - application/json
// security:
// - BearerAuth: []
// responses:
// '200':
// description: success
// '500':
// description: internal error
// schema:
// "$ref": "#/definitions/ErrorResponse"
if len(a.singleUserToken) > 0 {
// Not permitted in single-user mode
a.errorResponse(w, r.URL.Path, http.StatusUnauthorized, "not permitted in single-user mode", nil)
return
}
ctx := r.Context()
session := ctx.Value(sessionContextKey).(*model.Session)
auditRec := a.makeAuditRecord(r, "logout", audit.Fail)
defer a.audit.LogRecord(audit.LevelAuth, auditRec)
auditRec.AddMeta("userID", session.UserID)
if err := a.app.Logout(session.ID); err != nil {
a.errorResponse(w, r.URL.Path, http.StatusUnauthorized, "incorrect login", err)
return
}
auditRec.AddMeta("sessionID", session.ID)
jsonStringResponse(w, http.StatusOK, "{}")
auditRec.Success()
}
func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
// swagger:operation POST /api/v1/register register
//

View File

@ -119,6 +119,18 @@ func (a *App) Login(username, email, password, mfaToken string) (string, error)
return session.Token, nil
}
// Logout invalidates the user session.
func (a *App) Logout(sessionID string) error {
err := a.store.DeleteSession(sessionID)
if err != nil {
return errors.Wrap(err, "unable to delete the session")
}
a.metrics.IncrementLogoutCount(1)
return nil
}
// RegisterUser creates a new user if the provided data is valid.
func (a *App) RegisterUser(username, email, password string) error {
var user *model.User

View File

@ -31,6 +31,7 @@ type Metrics struct {
startTime prometheus.Gauge
loginCount prometheus.Counter
logoutCount prometheus.Counter
loginFailCount prometheus.Counter
blocksInsertedCount prometheus.Counter
@ -68,6 +69,15 @@ func NewMetrics(info InstanceInfo) *Metrics {
})
m.registry.MustRegister(m.loginCount)
m.logoutCount = prometheus.NewCounter(prometheus.CounterOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystemSystem,
Name: "logout_total",
Help: "Total number of logouts.",
ConstLabels: additionalLabels,
})
m.registry.MustRegister(m.logoutCount)
m.loginFailCount = prometheus.NewCounter(prometheus.CounterOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystemSystem,
@ -160,6 +170,12 @@ func (m *Metrics) IncrementLoginCount(num int) {
}
}
func (m *Metrics) IncrementLogoutCount(num int) {
if m != nil {
m.logoutCount.Add(float64(num))
}
}
func (m *Metrics) IncrementLoginFailCount(num int) {
if m != nil {
m.loginFailCount.Add(float64(num))

View File

@ -56,7 +56,7 @@ const SidebarUserMenu = React.memo(() => {
id='logout'
name={intl.formatMessage({id: 'Sidebar.logout', defaultMessage: 'Log out'})}
onClick={async () => {
octoClient.logout()
await octoClient.logout()
history.push('/login')
}}
/>

View File

@ -75,8 +75,18 @@ class OctoClient {
return false
}
logout(): void {
async logout(): Promise<boolean> {
const path = '/api/v1/logout'
const response = await fetch(this.getBaseURL() + path, {
method: 'POST',
headers: this.headers(),
})
localStorage.removeItem('focalboardSessionId')
if (response.status !== 200) {
return false
}
return true
}
async getClientConfig(): Promise<ClientConfig | null> {

View File

@ -20,8 +20,8 @@ const ErrorPage = React.memo(() => {
<br/>
<Button
filled={true}
onClick={() => {
octoClient.logout()
onClick={async () => {
await octoClient.logout()
window.location.href = '/login'
}}
>