2023-10-19 21:10:42 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/gin-gonic/gin"
|
2024-07-31 17:49:52 +00:00
|
|
|
lm "github.com/hrfee/jfa-go/logmessages"
|
2023-10-19 21:10:42 +00:00
|
|
|
"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
|
2023-10-20 21:16:40 +00:00
|
|
|
// @Router /activity [post]
|
2023-10-19 21:10:42 +00:00
|
|
|
// @Security Bearer
|
|
|
|
// @tags Activity
|
|
|
|
func (app *appContext) GetActivities(gc *gin.Context) {
|
|
|
|
req := GetActivitiesDTO{}
|
|
|
|
gc.BindJSON(&req)
|
|
|
|
query := &badgerhold.Query{}
|
2023-10-19 21:44:27 +00:00
|
|
|
activityTypes := make([]interface{}, len(req.Type))
|
|
|
|
for i, v := range req.Type {
|
|
|
|
activityTypes[i] = stringToActivityType(v)
|
|
|
|
}
|
|
|
|
if len(activityTypes) != 0 {
|
|
|
|
query = badgerhold.Where("Type").In(activityTypes...)
|
2023-10-19 21:10:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-21 23:28:01 +00:00
|
|
|
if !req.Ascending {
|
2023-10-19 21:10:42 +00:00
|
|
|
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 {
|
2024-07-31 17:49:52 +00:00
|
|
|
app.err.Printf(lm.FailedDBReadActivities, err)
|
2023-10-19 21:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resp := GetActivitiesRespDTO{
|
|
|
|
Activities: make([]ActivityDTO, len(results)),
|
2023-10-21 23:28:01 +00:00
|
|
|
LastPage: len(results) != req.Limit,
|
2023-10-19 21:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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(),
|
2023-12-23 21:47:41 +00:00
|
|
|
IP: act.IP,
|
2023-10-19 21:10:42 +00:00
|
|
|
}
|
2023-10-21 11:53:53 +00:00
|
|
|
if act.Type == ActivityDeletion || act.Type == ActivityCreation {
|
|
|
|
resp.Activities[i].Username = act.Value
|
|
|
|
resp.Activities[i].Value = ""
|
2024-08-06 13:48:31 +00:00
|
|
|
} else if user, err := app.jf.UserByID(act.UserID, false); err == nil {
|
2023-10-20 21:16:40 +00:00
|
|
|
resp.Activities[i].Username = user.Name
|
|
|
|
}
|
2023-10-21 11:53:53 +00:00
|
|
|
|
2023-10-20 21:16:40 +00:00
|
|
|
if (act.SourceType == ActivityUser || act.SourceType == ActivityAdmin) && act.Source != "" {
|
2024-08-06 13:48:31 +00:00
|
|
|
user, err := app.jf.UserByID(act.Source, false)
|
|
|
|
if err == nil {
|
2023-10-20 21:16:40 +00:00
|
|
|
resp.Activities[i].SourceUsername = user.Name
|
|
|
|
}
|
|
|
|
}
|
2023-10-19 21:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gc.JSON(200, resp)
|
|
|
|
}
|
2023-10-21 12:38:11 +00:00
|
|
|
|
|
|
|
// @Summary Delete the activity with the given ID. No-op if non-existent, always succeeds.
|
|
|
|
// @Produce json
|
|
|
|
// @Param id path string true "ID of activity to delete"
|
|
|
|
// @Success 200 {object} boolResponse
|
|
|
|
// @Router /activity/{id} [delete]
|
|
|
|
// @Security Bearer
|
|
|
|
// @tags Activity
|
|
|
|
func (app *appContext) DeleteActivity(gc *gin.Context) {
|
|
|
|
app.storage.DeleteActivityKey(gc.Param("id"))
|
|
|
|
respondBool(200, true, gc)
|
|
|
|
}
|
2023-10-23 10:34:04 +00:00
|
|
|
|
|
|
|
// @Summary Returns the total number of activities stored in the database.
|
|
|
|
// @Produce json
|
|
|
|
// @Success 200 {object} GetActivityCountDTO
|
|
|
|
// @Router /activity/count [get]
|
|
|
|
// @Security Bearer
|
|
|
|
// @tags Activity
|
|
|
|
func (app *appContext) GetActivityCount(gc *gin.Context) {
|
|
|
|
resp := GetActivityCountDTO{}
|
|
|
|
var err error
|
|
|
|
resp.Count, err = app.storage.db.Count(&Activity{}, &badgerhold.Query{})
|
|
|
|
if err != nil {
|
|
|
|
resp.Count = 0
|
|
|
|
}
|
|
|
|
gc.JSON(200, resp)
|
|
|
|
}
|