activity: render all activities correctly

the activity type, usernames, time, referrer, and invite code are
displayed correctly for all types of activity.
This commit is contained in:
Harvey Tindall 2023-10-21 12:53:53 +01:00
parent 1032e4e747
commit 44172074b9
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
6 changed files with 55 additions and 12 deletions

View File

@ -138,12 +138,15 @@ func (app *appContext) GetActivities(gc *gin.Context) {
Value: act.Value, Value: act.Value,
Time: act.Time.Unix(), Time: act.Time.Unix(),
} }
user, status, err := app.jf.UserByID(act.UserID, false) if act.Type == ActivityDeletion || act.Type == ActivityCreation {
if status == 200 && err == nil { resp.Activities[i].Username = act.Value
resp.Activities[i].Value = ""
} else if user, status, err := app.jf.UserByID(act.UserID, false); status == 200 && err == nil {
resp.Activities[i].Username = user.Name resp.Activities[i].Username = user.Name
} }
if (act.SourceType == ActivityUser || act.SourceType == ActivityAdmin) && act.Source != "" { if (act.SourceType == ActivityUser || act.SourceType == ActivityAdmin) && act.Source != "" {
user, status, err = app.jf.UserByID(act.Source, false) user, status, err := app.jf.UserByID(act.Source, false)
if status == 200 && err == nil { if status == 200 && err == nil {
resp.Activities[i].SourceUsername = user.Name resp.Activities[i].SourceUsername = user.Name
} }

View File

@ -53,6 +53,7 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
UserID: id, UserID: id,
SourceType: ActivityAdmin, SourceType: ActivityAdmin,
Source: gc.GetString("jfId"), Source: gc.GetString("jfId"),
Value: user.Name,
Time: time.Now(), Time: time.Now(),
}) })
@ -328,6 +329,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
SourceType: sourceType, SourceType: sourceType,
Source: source, Source: source,
InviteCode: invite.Code, InviteCode: invite.Code,
Value: user.Name,
Time: time.Now(), Time: time.Now(),
}) })
@ -648,6 +650,12 @@ func (app *appContext) DeleteUsers(gc *gin.Context) {
} }
} }
} }
username := ""
if user, status, err := app.jf.UserByID(userID, false); status == 200 && err == nil {
username = user.Name
}
status, err := app.jf.DeleteUser(userID) status, err := app.jf.DeleteUser(userID)
if !(status == 200 || status == 204) || err != nil { if !(status == 200 || status == 204) || err != nil {
msg := fmt.Sprintf("%d: %v", status, err) msg := fmt.Sprintf("%d: %v", status, err)
@ -664,6 +672,7 @@ func (app *appContext) DeleteUsers(gc *gin.Context) {
UserID: userID, UserID: userID,
SourceType: ActivityAdmin, SourceType: ActivityAdmin,
Source: gc.GetString("jfId"), Source: gc.GetString("jfId"),
Value: username,
Time: time.Now(), Time: time.Now(),
}) })
@ -1151,8 +1160,12 @@ func (app *appContext) ModifyEmails(gc *gin.Context) {
emailStore.Addr = address emailStore.Addr = address
app.storage.SetEmailsKey(id, emailStore) app.storage.SetEmailsKey(id, emailStore)
activityType := ActivityContactLinked
if address == "" {
activityType = ActivityContactUnlinked
}
app.storage.SetActivityKey(shortuuid.New(), Activity{ app.storage.SetActivityKey(shortuuid.New(), Activity{
Type: ActivityContactLinked, Type: activityType,
UserID: id, UserID: id,
SourceType: ActivityAdmin, SourceType: ActivityAdmin,
Source: gc.GetString("jfId"), Source: gc.GetString("jfId"),

View File

@ -147,7 +147,11 @@
"userDisabled": "User was disabled", "userDisabled": "User was disabled",
"inviteCreated": "Invite created: {invite}", "inviteCreated": "Invite created: {invite}",
"inviteDeleted": "Invite deleted: {invite}", "inviteDeleted": "Invite deleted: {invite}",
"inviteExpired": "Invite expired: {invite}" "inviteExpired": "Invite expired: {invite}",
"fromInvite": "From Invite",
"byAdmin": "By Admin",
"byUser": "By User",
"byJfaGo": "By jfa-go"
}, },
"notifications": { "notifications": {
"changedEmailAddress": "Changed email address of {n}.", "changedEmailAddress": "Changed email address of {n}.",

View File

@ -53,7 +53,7 @@ type Activity struct {
SourceType ActivitySource SourceType ActivitySource
Source string Source string
InviteCode string // Set for ActivityCreation, create/deleteInvite InviteCode string // Set for ActivityCreation, create/deleteInvite
Value string // Used for ActivityContactLinked, "email/discord/telegram/matrix", and Create/DeleteInvite, where it's the label. Value string // Used for ActivityContactLinked where it's "email/discord/telegram/matrix", Create/DeleteInvite, where it's the label, and Creation/Deletion, where it's the Username.
Time time.Time Time time.Time
} }

View File

@ -39,12 +39,20 @@ export class Activity { // FIXME: Add "implements"
private _expiryTypeBadge: HTMLElement; private _expiryTypeBadge: HTMLElement;
private _act: activity; private _act: activity;
_genUserText = (): string => {
return `<span class="font-medium">${this._act.username || this._act.user_id.substring(0, 5)}</span>`;
}
_genSrcUserText = (): string => {
return `<span class="font-medium">${this._act.source_username || this._act.source.substring(0, 5)}</span>`;
}
_genUserLink = (): string => { _genUserLink = (): string => {
return `<a class="font-medium hover:underline" href="/accounts/user/${this._act.user_id}">${this._act.username || this._act.user_id.substring(0, 5)}</a>`; return `<a class="hover:underline" href="/accounts/user/${this._act.user_id}">${this._genUserText()}</a>`;
} }
_genSrcUserLink = (): string => { _genSrcUserLink = (): string => {
return `<a class="font-medium hover:underline" href="/accounts/user/${this._act.source}">${this._act.source_username || this._act.source.substring(0, 5)}</a>`; return `<a class="hover:underline" href="/accounts/user/${this._act.source}">${this._genSrcUserText()}</a>`;
} }
private _renderInvText = (): string => { return `<span class="font-medium font-mono">${this.value || this.invite_code || "???"}</span>`; } private _renderInvText = (): string => { return `<span class="font-medium font-mono">${this.value || this.invite_code || "???"}</span>`; }
@ -102,12 +110,12 @@ export class Activity { // FIXME: Add "implements"
} }
} else if (this.type == "deletion") { } else if (this.type == "deletion") {
if (this.source_type == "daemon") { if (this.source_type == "daemon") {
this._title.innerHTML = window.lang.strings("accountExpired").replace("{user}", this._genUserLink()); this._title.innerHTML = window.lang.strings("accountExpired").replace("{user}", this._genUserText());
this._expiryTypeBadge.classList.add("~critical"); this._expiryTypeBadge.classList.add("~critical");
this._expiryTypeBadge.classList.remove("~info"); this._expiryTypeBadge.classList.remove("~info");
this._expiryTypeBadge.textContent = window.lang.strings("deleted"); this._expiryTypeBadge.textContent = window.lang.strings("deleted");
} else { } else {
this._title.innerHTML = window.lang.strings("accountDeleted").replace("{user}", this._genUserLink()); this._title.innerHTML = window.lang.strings("accountDeleted").replace("{user}", this._genUserText());
} }
} else if (this.type == "enabled") { } else if (this.type == "enabled") {
this._title.innerHTML = window.lang.strings("accountReEnabled").replace("{user}", this._genUserLink()); this._title.innerHTML = window.lang.strings("accountReEnabled").replace("{user}", this._genUserLink());
@ -151,6 +159,15 @@ export class Activity { // FIXME: Add "implements"
get source_type(): string { return this._act.source_type; } get source_type(): string { return this._act.source_type; }
set source_type(v: string) { set source_type(v: string) {
this._act.source_type = v; this._act.source_type = v;
if ((this.source_type == "anon" || this.source_type == "user") && this.type == "creation") {
this._sourceType.textContent = window.lang.strings("fromInvite");
} else if (this.source_type == "admin") {
this._sourceType.textContent = window.lang.strings("byAdmin");
} else if (this.source_type == "user" && this.type != "creation") {
this._sourceType.textContent = window.lang.strings("byUser");
} else if (this.source_type == "daemon") {
this._sourceType.textContent = window.lang.strings("byJfaGo");
}
} }
get invite_code(): string { return this._act.invite_code; } get invite_code(): string { return this._act.invite_code; }
@ -166,6 +183,11 @@ export class Activity { // FIXME: Add "implements"
get source(): string { return this._act.source; } get source(): string { return this._act.source; }
set source(v: string) { set source(v: string) {
this._act.source = v; this._act.source = v;
if ((this.source_type == "anon" || this.source_type == "user") && this.type == "creation") {
this._source.innerHTML = this._genInvLink();
} else if ((this.source_type == "admin" || this.source_type == "user") && this._act.source != "" && this._act.source_username != "") {
this._source.innerHTML = this._genSrcUserLink();
}
} }
constructor(act: activity) { constructor(act: activity) {
@ -180,7 +202,7 @@ export class Activity { // FIXME: Add "implements"
<span class="activity-expiry-type badge self-start md:self-end mt-1"></span> <span class="activity-expiry-type badge self-start md:self-end mt-1"></span>
</div> </div>
</div> </div>
<div class="flex justify-between"> <div class="flex flex-col md:flex-row justify-between">
<div> <div>
<span class="content supra mr-2 activity-source-type"></span><span class="activity-source"></span> <span class="content supra mr-2 activity-source-type"></span><span class="activity-source"></span>
</div> </div>
@ -228,7 +250,7 @@ export class activityList {
reload = () => { reload = () => {
let send = { let send = {
"type": [], "type": [],
"limit": 30, "limit": 60,
"page": 0, "page": 0,
"ascending": false "ascending": false
} }

View File

@ -107,6 +107,7 @@ func (app *appContext) checkUsers() {
if mode == "delete" { if mode == "delete" {
status, err = app.jf.DeleteUser(id) status, err = app.jf.DeleteUser(id)
activity.Type = ActivityDeletion activity.Type = ActivityDeletion
activity.Value = user.Name
} else if mode == "disable" { } else if mode == "disable" {
user.Policy.IsDisabled = true user.Policy.IsDisabled = true
// Admins can't be disabled // Admins can't be disabled