diff --git a/controllers/route.go b/controllers/route.go index 9109ff85..d75d981c 100644 --- a/controllers/route.go +++ b/controllers/route.go @@ -382,6 +382,11 @@ func (as *AdminServer) Login(w http.ResponseWriter, r *http.Request) { as.handleInvalidLogin(w, r) return } + u.LastLogin = time.Now().UTC() + err = models.PutUser(&u) + if err != nil { + log.Error(err) + } // If we've logged in, save the session and redirect to the dashboard session.Values["id"] = u.Id session.Save(r, w) diff --git a/db/db_mysql/migrations/20200914000000_0.11.0_last_login.sql b/db/db_mysql/migrations/20200914000000_0.11.0_last_login.sql new file mode 100644 index 00000000..b5f38120 --- /dev/null +++ b/db/db_mysql/migrations/20200914000000_0.11.0_last_login.sql @@ -0,0 +1,6 @@ +-- +goose Up +-- SQL in section 'Up' is executed when this migration is applied +ALTER TABLE `users` ADD COLUMN last_login datetime; + +-- +goose Down +-- SQL section 'Down' is executed when this migration is rolled back diff --git a/db/db_sqlite3/migrations/20200914000000_0.11.0_last_login.sql b/db/db_sqlite3/migrations/20200914000000_0.11.0_last_login.sql new file mode 100644 index 00000000..9a2aab62 --- /dev/null +++ b/db/db_sqlite3/migrations/20200914000000_0.11.0_last_login.sql @@ -0,0 +1,6 @@ +-- +goose Up +-- SQL in section 'Up' is executed when this migration is applied +ALTER TABLE users ADD COLUMN last_login datetime; + +-- +goose Down +-- SQL section 'Down' is executed when this migration is rolled back diff --git a/models/user.go b/models/user.go index 7db7821b..c1de9a29 100644 --- a/models/user.go +++ b/models/user.go @@ -2,6 +2,7 @@ package models import ( "errors" + "time" log "github.com/gophish/gophish/logger" ) @@ -13,13 +14,14 @@ var ErrModifyingOnlyAdmin = errors.New("Cannot remove the only administrator") // User represents the user model for gophish. type User struct { - Id int64 `json:"id"` - Username string `json:"username" sql:"not null;unique"` - Hash string `json:"-"` - ApiKey string `json:"api_key" sql:"not null;unique"` - Role Role `json:"role" gorm:"association_autoupdate:false;association_autocreate:false"` - RoleID int64 `json:"-"` - PasswordChangeRequired bool `json:"password_change_required"` + Id int64 `json:"id"` + Username string `json:"username" sql:"not null;unique"` + Hash string `json:"-"` + ApiKey string `json:"api_key" sql:"not null;unique"` + Role Role `json:"role" gorm:"association_autoupdate:false;association_autocreate:false"` + RoleID int64 `json:"-"` + PasswordChangeRequired bool `json:"password_change_required"` + LastLogin time.Time `json:"last_login"` } // GetUser returns the user that the given id corresponds to. If no user is found, an diff --git a/static/js/src/app/users.js b/static/js/src/app/users.js index ed5f18f5..01418be5 100644 --- a/static/js/src/app/users.js +++ b/static/js/src/app/users.js @@ -185,9 +185,14 @@ const load = () => { userTable.clear(); userRows = [] $.each(users, (i, user) => { + lastlogin = "Never" + if (user.last_login != "0001-01-01T00:00:00Z") { + lastlogin = moment(user.last_login).format('MMMM Do YYYY, h:mm:ss a') + } userRows.push([ escapeHtml(user.username), escapeHtml(user.role.name), + lastlogin, "
\