mirror of https://github.com/gophish/gophish
last_activity user field
parent
8e79294413
commit
ee47b3651a
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gophish/gophish/auth"
|
"github.com/gophish/gophish/auth"
|
||||||
ctx "github.com/gophish/gophish/context"
|
ctx "github.com/gophish/gophish/context"
|
||||||
|
@ -29,11 +30,12 @@ var ErrInsufficientPermission = errors.New("Permission denied")
|
||||||
|
|
||||||
// userRequest is the payload which represents the creation of a new user.
|
// userRequest is the payload which represents the creation of a new user.
|
||||||
type userRequest struct {
|
type userRequest struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
PasswordChangeRequired bool `json:"password_change_required"`
|
PasswordChangeRequired bool `json:"password_change_required"`
|
||||||
AccountLocked bool `json:"account_locked"`
|
AccountLocked bool `json:"account_locked"`
|
||||||
|
LastActivity time.Time `json:"last_acitvity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *userRequest) Validate(existingUser *models.User) error {
|
func (ur *userRequest) Validate(existingUser *models.User) error {
|
||||||
|
@ -109,7 +111,9 @@ func (as *Server) Users(w http.ResponseWriter, r *http.Request) {
|
||||||
Role: role,
|
Role: role,
|
||||||
RoleID: role.ID,
|
RoleID: role.ID,
|
||||||
PasswordChangeRequired: ur.PasswordChangeRequired,
|
PasswordChangeRequired: ur.PasswordChangeRequired,
|
||||||
|
LastActivity ur.LastActivity,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = models.PutUser(&user)
|
err = models.PutUser(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
|
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
|
||||||
|
|
|
@ -123,6 +123,7 @@ func (as *AdminServer) Shutdown() error {
|
||||||
func (as *AdminServer) registerRoutes() {
|
func (as *AdminServer) registerRoutes() {
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
// Base Front-end routes
|
// Base Front-end routes
|
||||||
|
router.Use(mid.UserActivityHandler)
|
||||||
router.HandleFunc("/", mid.Use(as.Base, mid.RequireLogin))
|
router.HandleFunc("/", mid.Use(as.Base, mid.RequireLogin))
|
||||||
router.HandleFunc("/login", mid.Use(as.Login, as.limiter.Limit))
|
router.HandleFunc("/login", mid.Use(as.Login, as.limiter.Limit))
|
||||||
router.HandleFunc("/logout", mid.Use(as.Logout, mid.RequireLogin))
|
router.HandleFunc("/logout", mid.Use(as.Logout, mid.RequireLogin))
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
-- +goose Up
|
||||||
|
-- SQL in section 'Up' is executed when this migration is applied
|
||||||
|
ALTER TABLE `users`
|
||||||
|
ADD COLUMN `last_acitivty` DATETIME NULL;
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- SQL section 'Down' is executed when this migration is rolled back
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
-- +goose Up
|
||||||
|
-- SQL in section 'Up' is executed when this migration is applied
|
||||||
|
ALTER TABLE `users`
|
||||||
|
ADD COLUMN `last_acitivty` DATETIME NULL;
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- SQL section 'Down' is executed when this migration is rolled back
|
||||||
|
|
|
@ -5,8 +5,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
ctx "github.com/gophish/gophish/context"
|
ctx "github.com/gophish/gophish/context"
|
||||||
|
log "github.com/gophish/gophish/logger"
|
||||||
"github.com/gophish/gophish/models"
|
"github.com/gophish/gophish/models"
|
||||||
"github.com/gorilla/csrf"
|
"github.com/gorilla/csrf"
|
||||||
)
|
)
|
||||||
|
@ -39,6 +41,24 @@ func Use(handler http.HandlerFunc, mid ...func(http.Handler) http.HandlerFunc) h
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UserActivityHandler(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Update the LastActivity timestamp for the logged-in user
|
||||||
|
if u := ctx.Get(r, "user"); u != nil {
|
||||||
|
currentUser := u.(models.User)
|
||||||
|
currentUser.LastActivity = time.Now()
|
||||||
|
if err := models.PutUser(¤tUser); err != nil {
|
||||||
|
// Handle error
|
||||||
|
log.Errorf("Failed to update user last activity: %v", err)
|
||||||
|
http.Error(w, "Failed to update user last activity", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Call the next handler in the chain
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// GetContext wraps each request in a function which fills in the context for a given request.
|
// GetContext wraps each request in a function which fills in the context for a given request.
|
||||||
// This includes setting the User and Session keys and values as necessary for use in later functions.
|
// This includes setting the User and Session keys and values as necessary for use in later functions.
|
||||||
func GetContext(handler http.Handler) http.HandlerFunc {
|
func GetContext(handler http.Handler) http.HandlerFunc {
|
||||||
|
|
|
@ -23,6 +23,7 @@ type User struct {
|
||||||
PasswordChangeRequired bool `json:"password_change_required"`
|
PasswordChangeRequired bool `json:"password_change_required"`
|
||||||
AccountLocked bool `json:"account_locked"`
|
AccountLocked bool `json:"account_locked"`
|
||||||
LastLogin time.Time `json:"last_login"`
|
LastLogin time.Time `json:"last_login"`
|
||||||
|
LastActivity time.Time `json:"last_activity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUser returns the user that the given id corresponds to. If no user is found, an
|
// GetUser returns the user that the given id corresponds to. If no user is found, an
|
||||||
|
|
Loading…
Reference in New Issue