mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
activity: implement most initial logging
resetPassword, changePassword, delete/createInvite, enable/disable, creation/deletion of invites & users are all done, only remaining one is account linking.
This commit is contained in:
parent
2c787b4d46
commit
b620c0d9ae
@ -85,6 +85,13 @@ func (app *appContext) checkInvites() {
|
||||
wait.Wait()
|
||||
}
|
||||
app.storage.DeleteInvitesKey(data.Code)
|
||||
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityDeleteInvite,
|
||||
SourceType: ActivityDaemon,
|
||||
InviteCode: data.Code,
|
||||
Time: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,12 +137,24 @@ func (app *appContext) checkInvite(code string, used bool, username string) bool
|
||||
}
|
||||
match = false
|
||||
app.storage.DeleteInvitesKey(code)
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityDeleteInvite,
|
||||
SourceType: ActivityDaemon,
|
||||
InviteCode: code,
|
||||
Time: time.Now(),
|
||||
})
|
||||
} else if used {
|
||||
del := false
|
||||
newInv := inv
|
||||
if newInv.RemainingUses == 1 {
|
||||
del = true
|
||||
app.storage.DeleteInvitesKey(code)
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityDeleteInvite,
|
||||
SourceType: ActivityDaemon,
|
||||
InviteCode: code,
|
||||
Time: time.Now(),
|
||||
})
|
||||
} else if newInv.RemainingUses != 0 {
|
||||
// 0 means infinite i guess?
|
||||
newInv.RemainingUses--
|
||||
@ -236,6 +255,17 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
|
||||
}
|
||||
}
|
||||
app.storage.SetInvitesKey(invite.Code, invite)
|
||||
|
||||
// Record activity
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityCreateInvite,
|
||||
UserID: "",
|
||||
SourceType: ActivityAdmin,
|
||||
Source: gc.GetString("jfId"),
|
||||
InviteCode: invite.Code,
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
respondBool(200, true, gc)
|
||||
}
|
||||
|
||||
@ -433,6 +463,15 @@ func (app *appContext) DeleteInvite(gc *gin.Context) {
|
||||
_, ok = app.storage.GetInvitesKey(req.Code)
|
||||
if ok {
|
||||
app.storage.DeleteInvitesKey(req.Code)
|
||||
|
||||
// Record activity
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityDeleteInvite,
|
||||
SourceType: ActivityAdmin,
|
||||
Source: gc.GetString("jfId"),
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
app.info.Printf("%s: Invite deleted", req.Code)
|
||||
respondBool(200, true, gc)
|
||||
return
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/lithammer/shortuuid/v3"
|
||||
"github.com/timshannon/badgerhold/v4"
|
||||
)
|
||||
|
||||
@ -620,6 +621,15 @@ func (app *appContext) ChangeMyPassword(gc *gin.Context) {
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityChangePassword,
|
||||
UserID: user.ID,
|
||||
SourceType: ActivityUser,
|
||||
Source: user.ID,
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||
func() {
|
||||
ombiUser, status, err := app.getOmbiUser(gc.GetString("jfId"))
|
||||
|
24
api-users.go
24
api-users.go
@ -567,6 +567,10 @@ func (app *appContext) EnableDisableUsers(gc *gin.Context) {
|
||||
sendMail = false
|
||||
}
|
||||
}
|
||||
activityType := ActivityDisabled
|
||||
if req.Enabled {
|
||||
activityType = ActivityEnabled
|
||||
}
|
||||
for _, userID := range req.Users {
|
||||
user, status, err := app.jf.UserByID(userID, false)
|
||||
if status != 200 || err != nil {
|
||||
@ -581,6 +585,16 @@ func (app *appContext) EnableDisableUsers(gc *gin.Context) {
|
||||
app.err.Printf("Failed to set policy for user \"%s\" (%d): %v", userID, status, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Record activity
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: activityType,
|
||||
UserID: userID,
|
||||
SourceType: ActivityAdmin,
|
||||
Source: gc.GetString("jfId"),
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
if sendMail && req.Notify {
|
||||
if err := app.sendByID(msg, userID); err != nil {
|
||||
app.err.Printf("Failed to send account enabled/disabled email: %v", err)
|
||||
@ -642,6 +656,16 @@ func (app *appContext) DeleteUsers(gc *gin.Context) {
|
||||
errors[userID] += msg
|
||||
}
|
||||
}
|
||||
|
||||
// Record activity
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityDeletion,
|
||||
UserID: userID,
|
||||
SourceType: ActivityAdmin,
|
||||
Source: gc.GetString("jfId"),
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
if sendMail && req.Notify {
|
||||
if err := app.sendByID(msg, userID); err != nil {
|
||||
app.err.Printf("Failed to send account deletion email: %v", err)
|
||||
|
11
api.go
11
api.go
@ -7,6 +7,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/hrfee/mediabrowser"
|
||||
"github.com/itchyny/timefmt-go"
|
||||
"github.com/lithammer/shortuuid/v3"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
@ -157,6 +158,7 @@ func (app *appContext) ResetSetPassword(gc *gin.Context) {
|
||||
}
|
||||
username = resp.UsersReset[0]
|
||||
}
|
||||
|
||||
var user mediabrowser.User
|
||||
var status int
|
||||
var err error
|
||||
@ -170,6 +172,15 @@ func (app *appContext) ResetSetPassword(gc *gin.Context) {
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityResetPassword,
|
||||
UserID: user.ID,
|
||||
SourceType: ActivityUser,
|
||||
Source: user.ID,
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
prevPassword := req.PIN
|
||||
if isInternal {
|
||||
prevPassword = ""
|
||||
|
@ -39,13 +39,14 @@ type ActivitySource int
|
||||
|
||||
const (
|
||||
ActivityUser ActivitySource = iota // Source = UserID. For ActivityCreation, this would mean the referrer.
|
||||
ActivityAdmin // Source = Admin's UserID, or simply just "admin"
|
||||
ActivityAdmin // Source = Admin's UserID, or blank if jellyfin login isn't on.
|
||||
ActivityAnon // Source = Blank, or potentially browser info. For ActivityCreation, this would be via an invite
|
||||
ActivityDaemon // Source = Blank, was deleted/disabled due to expiry by daemon
|
||||
)
|
||||
|
||||
type Activity struct {
|
||||
Type ActivityType `badgerhold:"index"`
|
||||
UserID string
|
||||
UserID string // ID of target user. For account creation, this will be the newly created account
|
||||
SourceType ActivitySource
|
||||
Source string
|
||||
InviteCode string // Only set for ActivityCreation
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hrfee/mediabrowser"
|
||||
"github.com/lithammer/shortuuid/v3"
|
||||
)
|
||||
|
||||
type userDaemon struct {
|
||||
@ -95,18 +96,31 @@ func (app *appContext) checkUsers() {
|
||||
continue
|
||||
}
|
||||
app.info.Printf("%s expired user \"%s\"", termPlural, user.Name)
|
||||
|
||||
// Record activity
|
||||
activity := Activity{
|
||||
UserID: id,
|
||||
SourceType: ActivityDaemon,
|
||||
Time: time.Now(),
|
||||
}
|
||||
|
||||
if mode == "delete" {
|
||||
status, err = app.jf.DeleteUser(id)
|
||||
activity.Type = ActivityDeletion
|
||||
} else if mode == "disable" {
|
||||
user.Policy.IsDisabled = true
|
||||
// Admins can't be disabled
|
||||
user.Policy.IsAdministrator = false
|
||||
status, err = app.jf.SetPolicy(id, user.Policy)
|
||||
activity.Type = ActivityDisabled
|
||||
}
|
||||
if !(status == 200 || status == 204) || err != nil {
|
||||
app.err.Printf("Failed to %s \"%s\" (%d): %s", mode, user.Name, status, err)
|
||||
continue
|
||||
}
|
||||
|
||||
app.storage.SetActivityKey(shortuuid.New(), activity)
|
||||
|
||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
||||
app.jf.CacheExpiry = time.Now()
|
||||
if contact {
|
||||
|
17
views.go
17
views.go
@ -17,6 +17,7 @@ import (
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/hrfee/mediabrowser"
|
||||
"github.com/lithammer/shortuuid/v3"
|
||||
"github.com/steambap/captcha"
|
||||
)
|
||||
|
||||
@ -329,6 +330,7 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
||||
}
|
||||
username = pwr.Username
|
||||
}
|
||||
|
||||
if (status == 200 || status == 204) && err == nil && (isInternal || resp.Success) {
|
||||
data["success"] = true
|
||||
data["pin"] = pin
|
||||
@ -338,6 +340,21 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
||||
} else {
|
||||
app.err.Printf("Password Reset failed (%d): %v", status, err)
|
||||
}
|
||||
|
||||
// Only log PWRs we know the user for.
|
||||
if username != "" {
|
||||
jfUser, status, err := app.jf.UserByName(username, false)
|
||||
if err == nil && status == 200 {
|
||||
app.storage.SetActivityKey(shortuuid.New(), Activity{
|
||||
Type: ActivityResetPassword,
|
||||
UserID: jfUser.ID,
|
||||
SourceType: ActivityUser,
|
||||
Source: jfUser.ID,
|
||||
Time: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||
jfUser, status, err := app.jf.UserByName(username, false)
|
||||
if status != 200 || err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user