mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
activity: route to show activity activity log
filterable by type, sortable by time, and paginated.
This commit is contained in:
parent
9d1c7bba6f
commit
df1581d48e
141
api-activities.go
Normal file
141
api-activities.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/timshannon/badgerhold/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func stringToActivityType(v string) ActivityType {
|
||||||
|
switch v {
|
||||||
|
case "creation":
|
||||||
|
return ActivityCreation
|
||||||
|
case "deletion":
|
||||||
|
return ActivityDeletion
|
||||||
|
case "disabled":
|
||||||
|
return ActivityDisabled
|
||||||
|
case "enabled":
|
||||||
|
return ActivityEnabled
|
||||||
|
case "contactLinked":
|
||||||
|
return ActivityContactLinked
|
||||||
|
case "contactUnlinked":
|
||||||
|
return ActivityContactUnlinked
|
||||||
|
case "changePassword":
|
||||||
|
return ActivityChangePassword
|
||||||
|
case "resetPassword":
|
||||||
|
return ActivityResetPassword
|
||||||
|
case "createInvite":
|
||||||
|
return ActivityCreateInvite
|
||||||
|
case "deleteInvite":
|
||||||
|
return ActivityDeleteInvite
|
||||||
|
}
|
||||||
|
return ActivityUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
func activityTypeToString(v ActivityType) string {
|
||||||
|
switch v {
|
||||||
|
case ActivityCreation:
|
||||||
|
return "creation"
|
||||||
|
case ActivityDeletion:
|
||||||
|
return "deletion"
|
||||||
|
case ActivityDisabled:
|
||||||
|
return "disabled"
|
||||||
|
case ActivityEnabled:
|
||||||
|
return "enabled"
|
||||||
|
case ActivityContactLinked:
|
||||||
|
return "contactLinked"
|
||||||
|
case ActivityContactUnlinked:
|
||||||
|
return "contactUnlinked"
|
||||||
|
case ActivityChangePassword:
|
||||||
|
return "changePassword"
|
||||||
|
case ActivityResetPassword:
|
||||||
|
return "resetPassword"
|
||||||
|
case ActivityCreateInvite:
|
||||||
|
return "createInvite"
|
||||||
|
case ActivityDeleteInvite:
|
||||||
|
return "deleteInvite"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringToActivitySource(v string) ActivitySource {
|
||||||
|
switch v {
|
||||||
|
case "user":
|
||||||
|
return ActivityUser
|
||||||
|
case "admin":
|
||||||
|
return ActivityAdmin
|
||||||
|
case "anon":
|
||||||
|
return ActivityAnon
|
||||||
|
case "daemon":
|
||||||
|
return ActivityDaemon
|
||||||
|
}
|
||||||
|
return ActivityAnon
|
||||||
|
}
|
||||||
|
|
||||||
|
func activitySourceToString(v ActivitySource) string {
|
||||||
|
switch v {
|
||||||
|
case ActivityUser:
|
||||||
|
return "user"
|
||||||
|
case ActivityAdmin:
|
||||||
|
return "admin"
|
||||||
|
case ActivityAnon:
|
||||||
|
return "anon"
|
||||||
|
case ActivityDaemon:
|
||||||
|
return "daemon"
|
||||||
|
}
|
||||||
|
return "anon"
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get the requested set of activities, Paginated, filtered and sorted.
|
||||||
|
// @Produce json
|
||||||
|
// @Param GetActivitiesDTO body GetActivitiesDTO true "search parameters"
|
||||||
|
// @Success 200 {object} GetActivitiesRespDTO
|
||||||
|
// @Router /activity [get]
|
||||||
|
// @Security Bearer
|
||||||
|
// @tags Activity
|
||||||
|
func (app *appContext) GetActivities(gc *gin.Context) {
|
||||||
|
req := GetActivitiesDTO{}
|
||||||
|
gc.BindJSON(&req)
|
||||||
|
query := &badgerhold.Query{}
|
||||||
|
activityType := stringToActivityType(req.Type)
|
||||||
|
if activityType != ActivityUnknown {
|
||||||
|
query = badgerhold.Where("Type").Eq(activityType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Ascending {
|
||||||
|
query = query.Reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.SortBy("Time")
|
||||||
|
|
||||||
|
if req.Limit == 0 {
|
||||||
|
req.Limit = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.Skip(req.Page * req.Limit).Limit(req.Limit)
|
||||||
|
|
||||||
|
var results []Activity
|
||||||
|
err := app.storage.db.Find(&results, query)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf("Failed to read activities from DB: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := GetActivitiesRespDTO{
|
||||||
|
Activities: make([]ActivityDTO, len(results)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, act := range results {
|
||||||
|
resp.Activities[i] = ActivityDTO{
|
||||||
|
ID: act.ID,
|
||||||
|
Type: activityTypeToString(act.Type),
|
||||||
|
UserID: act.UserID,
|
||||||
|
SourceType: activitySourceToString(act.SourceType),
|
||||||
|
Source: act.Source,
|
||||||
|
InviteCode: act.InviteCode,
|
||||||
|
Value: act.Value,
|
||||||
|
Time: act.Time.Unix(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gc.JSON(200, resp)
|
||||||
|
}
|
3
main.go
3
main.go
@ -638,6 +638,9 @@ func flagPassed(name string) (found bool) {
|
|||||||
// @tag.name Profiles & Settings
|
// @tag.name Profiles & Settings
|
||||||
// @tag.description Profile and settings related operations.
|
// @tag.description Profile and settings related operations.
|
||||||
|
|
||||||
|
// @tag.name Activity
|
||||||
|
// @tag.description Routes related to the activity log.
|
||||||
|
|
||||||
// @tag.name Configuration
|
// @tag.name Configuration
|
||||||
// @tag.description jfa-go settings.
|
// @tag.description jfa-go settings.
|
||||||
|
|
||||||
|
22
models.go
22
models.go
@ -430,3 +430,25 @@ type GetMyReferralRespDTO struct {
|
|||||||
type EnableDisableReferralDTO struct {
|
type EnableDisableReferralDTO struct {
|
||||||
Users []string `json:"users"`
|
Users []string `json:"users"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ActivityDTO struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
SourceType string `json:"source_type"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
InviteCode string `json:"invite_code"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetActivitiesDTO struct {
|
||||||
|
Type string `json:"type"` // Type of activity to get. Leave blank for all.
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Page int `json:"page"` // zero-indexed
|
||||||
|
Ascending bool `json:"ascending"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetActivitiesRespDTO struct {
|
||||||
|
Activities []ActivityDTO `json:"activities"`
|
||||||
|
}
|
||||||
|
@ -232,6 +232,8 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
api.DELETE(p+"/profiles/referral/:profile", app.DisableReferralForProfile)
|
api.DELETE(p+"/profiles/referral/:profile", app.DisableReferralForProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api.GET(p+"/activity", app.GetActivities)
|
||||||
|
|
||||||
if userPageEnabled {
|
if userPageEnabled {
|
||||||
user.GET("/details", app.MyDetails)
|
user.GET("/details", app.MyDetails)
|
||||||
user.POST("/contact", app.SetMyContactMethods)
|
user.POST("/contact", app.SetMyContactMethods)
|
||||||
|
@ -34,6 +34,7 @@ const (
|
|||||||
ActivityResetPassword
|
ActivityResetPassword
|
||||||
ActivityCreateInvite
|
ActivityCreateInvite
|
||||||
ActivityDeleteInvite
|
ActivityDeleteInvite
|
||||||
|
ActivityUnknown
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActivitySource int
|
type ActivitySource int
|
||||||
@ -46,6 +47,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Activity struct {
|
type Activity struct {
|
||||||
|
ID string `badgerhold:"key"`
|
||||||
Type ActivityType `badgerhold:"index"`
|
Type ActivityType `badgerhold:"index"`
|
||||||
UserID string // ID of target user. For account creation, this will be the newly created account
|
UserID string // ID of target user. For account creation, this will be the newly created account
|
||||||
SourceType ActivitySource
|
SourceType ActivitySource
|
||||||
@ -562,6 +564,7 @@ func (st *Storage) GetActivityKey(k string) (Activity, bool) {
|
|||||||
|
|
||||||
// SetActivityKey stores value v in key k.
|
// SetActivityKey stores value v in key k.
|
||||||
func (st *Storage) SetActivityKey(k string, v Activity) {
|
func (st *Storage) SetActivityKey(k string, v Activity) {
|
||||||
|
v.ID = k
|
||||||
err := st.db.Upsert(k, v)
|
err := st.db.Upsert(k, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// fmt.Printf("Failed to set custom content: %v\n", err)
|
// fmt.Printf("Failed to set custom content: %v\n", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user