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,
Time: act.Time.Unix(),
}
user, status, err := app.jf.UserByID(act.UserID, false)
if status == 200 && err == nil {
if act.Type == ActivityDeletion || act.Type == ActivityCreation {
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
}
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 {
resp.Activities[i].SourceUsername = user.Name
}

View File

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

View File

@ -147,7 +147,11 @@
"userDisabled": "User was disabled",
"inviteCreated": "Invite created: {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": {
"changedEmailAddress": "Changed email address of {n}.",

View File

@ -53,7 +53,7 @@ type Activity struct {
SourceType ActivitySource
Source string
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
}

View File

@ -39,12 +39,20 @@ export class Activity { // FIXME: Add "implements"
private _expiryTypeBadge: HTMLElement;
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 => {
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 => {
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>`; }
@ -102,12 +110,12 @@ export class Activity { // FIXME: Add "implements"
}
} else if (this.type == "deletion") {
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.remove("~info");
this._expiryTypeBadge.textContent = window.lang.strings("deleted");
} 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") {
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; }
set source_type(v: string) {
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; }
@ -166,6 +183,11 @@ export class Activity { // FIXME: Add "implements"
get source(): string { return this._act.source; }
set source(v: string) {
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) {
@ -180,7 +202,7 @@ export class Activity { // FIXME: Add "implements"
<span class="activity-expiry-type badge self-start md:self-end mt-1"></span>
</div>
</div>
<div class="flex justify-between">
<div class="flex flex-col md:flex-row justify-between">
<div>
<span class="content supra mr-2 activity-source-type"></span><span class="activity-source"></span>
</div>
@ -228,7 +250,7 @@ export class activityList {
reload = () => {
let send = {
"type": [],
"limit": 30,
"limit": 60,
"page": 0,
"ascending": false
}

View File

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