1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 17:10:10 +00:00

referrals: Show enabled status on account list

This commit is contained in:
Harvey Tindall 2023-09-06 22:46:16 +01:00
parent cdc8f9af4b
commit 729552a827
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
5 changed files with 54 additions and 6 deletions

View File

@ -643,7 +643,7 @@ func (app *appContext) GetMyReferral(gc *gin.Context) {
// If one exists, that means its just for us and so we // If one exists, that means its just for us and so we
// can use it directly. // can use it directly.
inv := Invite{} inv := Invite{}
err := app.storage.db.Find(&inv, badgerhold.Where("ReferrerJellyfinID").Eq(gc.GetString("jfId"))) err := app.storage.db.FindOne(&inv, badgerhold.Where("ReferrerJellyfinID").Eq(gc.GetString("jfId")))
if err != nil { if err != nil {
// 2. Look for a template matching the key found in the user storage // 2. Look for a template matching the key found in the user storage
// Since this key is shared between users in a profile, we make a copy. // Since this key is shared between users in a profile, we make a copy.
@ -664,6 +664,7 @@ func (app *appContext) GetMyReferral(gc *gin.Context) {
inv.Created = time.Now() inv.Created = time.Now()
inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour) inv.ValidTill = inv.Created.Add(REFERRAL_EXPIRY_DAYS * 24 * time.Hour)
inv.IsReferral = true inv.IsReferral = true
inv.ReferrerJellyfinID = gc.GetString("jfId")
app.storage.SetInvitesKey(inv.Code, inv) app.storage.SetInvitesKey(inv.Code, inv)
} else if time.Now().After(inv.ValidTill) { } else if time.Now().After(inv.ValidTill) {
// 3. We found an invite for us, but it's expired. // 3. We found an invite for us, but it's expired.

View File

@ -11,6 +11,7 @@ import (
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt"
"github.com/hrfee/mediabrowser" "github.com/hrfee/mediabrowser"
"github.com/lithammer/shortuuid/v3" "github.com/lithammer/shortuuid/v3"
"github.com/timshannon/badgerhold/v4"
) )
// @Summary Creates a new Jellyfin user without an invite. // @Summary Creates a new Jellyfin user without an invite.
@ -668,6 +669,10 @@ func (app *appContext) EnableReferralForUsers(gc *gin.Context) {
} }
} }
for _, u := range req.Users { for _, u := range req.Users {
// 1. Wipe out any existing referral codes.
app.storage.db.DeleteMatching(Invite{}, badgerhold.Where("ReferrerJellyfinID").Eq(u))
// 2. Generate referral invite.
inv := baseInv inv := baseInv
inv.Code = shortuuid.New() inv.Code = shortuuid.New()
// make sure code doesn't begin with number // make sure code doesn't begin with number
@ -888,13 +893,15 @@ func (app *appContext) GetUsers(gc *gin.Context) {
} }
adminOnly := app.config.Section("ui").Key("admin_only").MustBool(true) adminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
allowAll := app.config.Section("ui").Key("allow_all").MustBool(false) allowAll := app.config.Section("ui").Key("allow_all").MustBool(false)
referralsEnabled := app.config.Section("user_page").Key("referrals").MustBool(false)
i := 0 i := 0
for _, jfUser := range users { for _, jfUser := range users {
user := respUser{ user := respUser{
ID: jfUser.ID, ID: jfUser.ID,
Name: jfUser.Name, Name: jfUser.Name,
Admin: jfUser.Policy.IsAdministrator, Admin: jfUser.Policy.IsAdministrator,
Disabled: jfUser.Policy.IsDisabled, Disabled: jfUser.Policy.IsDisabled,
ReferralsEnabled: false,
} }
if !jfUser.LastActivityDate.IsZero() { if !jfUser.LastActivityDate.IsZero() {
user.LastActive = jfUser.LastActivityDate.Unix() user.LastActive = jfUser.LastActivityDate.Unix()
@ -923,6 +930,18 @@ func (app *appContext) GetUsers(gc *gin.Context) {
user.DiscordID = dcUser.ID user.DiscordID = dcUser.ID
user.NotifyThroughDiscord = dcUser.Contact user.NotifyThroughDiscord = dcUser.Contact
} }
// FIXME: Send referral data
referrerInv := Invite{}
if referralsEnabled {
// 1. Directly attached invite.
err := app.storage.db.FindOne(&referrerInv, badgerhold.Where("ReferrerJellyfinID").Eq(jfUser.ID))
if err == nil {
user.ReferralsEnabled = true
// 2. Referrals via profile template. Shallow check, doesn't look for the thing in the database.
} else if email, ok := app.storage.GetEmailsKey(jfUser.ID); ok && email.ReferralTemplateKey != "" {
user.ReferralsEnabled = true
}
}
resp.UserList[i] = user resp.UserList[i] = user
i++ i++
} }

View File

@ -693,6 +693,9 @@
{{ if .discordEnabled }} {{ if .discordEnabled }}
<th class="text-center-i grid gap-4 place-items-stretch accounts-header-discord">Discord</th> <th class="text-center-i grid gap-4 place-items-stretch accounts-header-discord">Discord</th>
{{ end }} {{ end }}
{{ if .referralsEnabled }}
<th class="text-center-i grid gap-4 place-items-stretch accounts-header-referrals">{{ .strings.referrals }}</th>
{{ end }}
<th class="grid gap-4 place-items-stretch accounts-header-expiry">{{ .strings.expiry }}</th> <th class="grid gap-4 place-items-stretch accounts-header-expiry">{{ .strings.expiry }}</th>
<th class="grid gap-4 place-items-stretch accounts-header-last-active">{{ .strings.lastActiveTime }}</th> <th class="grid gap-4 place-items-stretch accounts-header-last-active">{{ .strings.lastActiveTime }}</th>
</tr> </tr>

View File

@ -151,6 +151,7 @@ type respUser struct {
NotifyThroughMatrix bool `json:"notify_matrix"` NotifyThroughMatrix bool `json:"notify_matrix"`
Label string `json:"label"` // Label of user, shown next to their name. Label string `json:"label"` // Label of user, shown next to their name.
AccountsAdmin bool `json:"accounts_admin"` // Whether or not the user is a jfa-go admin. AccountsAdmin bool `json:"accounts_admin"` // Whether or not the user is a jfa-go admin.
ReferralsEnabled bool `json:"referrals_enabled"`
} }
type getUsersDTO struct { type getUsersDTO struct {

View File

@ -23,6 +23,7 @@ interface User {
notify_matrix: boolean; notify_matrix: boolean;
label: string; label: string;
accounts_admin: boolean; accounts_admin: boolean;
referrals_enabled: boolean;
} }
interface getPinResponse { interface getPinResponse {
@ -69,6 +70,8 @@ class user implements User {
private _labelEditButton: HTMLElement; private _labelEditButton: HTMLElement;
private _accounts_admin: HTMLInputElement private _accounts_admin: HTMLInputElement
private _selected: boolean; private _selected: boolean;
private _referralsEnabled: boolean;
private _referralsEnabledCheck: HTMLElement;
lastNotifyMethod = (): string => { lastNotifyMethod = (): string => {
// Telegram, Matrix, Discord // Telegram, Matrix, Discord
@ -162,6 +165,17 @@ class user implements User {
} }
} }
get referrals_enabled(): boolean { return this._referralsEnabled; }
set referrals_enabled(v: boolean) {
this._referralsEnabled = v;
if (!window.referralsEnabled) return;
if (!v) {
this._referralsEnabledCheck.textContent = ``;
} else {
this._referralsEnabledCheck.innerHTML = `<i class="ri-check-line" aria-label="${window.lang.strings("enabled")}"></i>`;
}
}
private _constructDropdown = (): HTMLDivElement => { private _constructDropdown = (): HTMLDivElement => {
const el = document.createElement("div") as HTMLDivElement; const el = document.createElement("div") as HTMLDivElement;
const telegram = this._telegramUsername != ""; const telegram = this._telegramUsername != "";
@ -506,6 +520,11 @@ class user implements User {
<td class="accounts-discord"></td> <td class="accounts-discord"></td>
`; `;
} }
if (window.referralsEnabled) {
innerHTML += `
<td class="accounts-referrals text-center-i grid gap-4 place-items-stretch"></td>
`;
}
innerHTML += ` innerHTML += `
<td class="accounts-expiry"></td> <td class="accounts-expiry"></td>
<td class="accounts-last-active whitespace-nowrap"></td> <td class="accounts-last-active whitespace-nowrap"></td>
@ -545,6 +564,10 @@ class user implements User {
}; };
} }
if (window.referralsEnabled) {
this._referralsEnabledCheck = this._row.querySelector(".accounts-referrals");
}
this._notifyDropdown = this._constructDropdown(); this._notifyDropdown = this._constructDropdown();
const toggleEmailInput = () => { const toggleEmailInput = () => {
@ -716,6 +739,7 @@ class user implements User {
this.discord_id = user.discord_id; this.discord_id = user.discord_id;
this.label = user.label; this.label = user.label;
this.accounts_admin = user.accounts_admin; this.accounts_admin = user.accounts_admin;
this.referrals_enabled = user.referrals_enabled;
} }
asElement = (): HTMLTableRowElement => { return this._row; } asElement = (): HTMLTableRowElement => { return this._row; }
@ -1061,7 +1085,7 @@ export class accountsList {
let attempt: { year?: number, month?: number, day?: number, hour?: number, minute?: number } = dateParser.attempt(split[1]); let attempt: { year?: number, month?: number, day?: number, hour?: number, minute?: number } = dateParser.attempt(split[1]);
// Month in Date objects is 0-based, so make our parsed date that way too // Month in Date objects is 0-based, so make our parsed date that way too
if ("month" in attempt) attempt["month"] -= 1; if ("month" in attempt) attempt.month -= 1;
let date: Date = (Date as any).fromString(split[1]) as Date; let date: Date = (Date as any).fromString(split[1]) as Date;
console.log("Read", attempt, "and", date); console.log("Read", attempt, "and", date);