mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
use unix timestamp for inv created & usedBy
usedBy is still stored as a string in invites.json to cope with existing invites with times stored formatted. knz/strtime requires cgo for strptime, so it has been replaced with the native itchyny/timefmt-go.
This commit is contained in:
parent
6ec2186bdf
commit
3f8414c70a
24
api.go
24
api.go
@ -11,7 +11,7 @@ import (
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/hrfee/mediabrowser"
|
||||
"github.com/knz/strtime"
|
||||
"github.com/itchyny/timefmt-go"
|
||||
"github.com/lithammer/shortuuid/v3"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
@ -48,8 +48,8 @@ func (app *appContext) loadStrftime() {
|
||||
}
|
||||
|
||||
func (app *appContext) prettyTime(dt time.Time) (date, time string) {
|
||||
date, _ = strtime.Strftime(dt, app.datePattern)
|
||||
time, _ = strtime.Strftime(dt, app.timePattern)
|
||||
date = timefmt.Format(dt, app.datePattern)
|
||||
time = timefmt.Format(dt, app.timePattern)
|
||||
return
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ func (app *appContext) checkInvite(code string, used bool, username string) bool
|
||||
// 0 means infinite i guess?
|
||||
newInv.RemainingUses--
|
||||
}
|
||||
newInv.UsedBy = append(newInv.UsedBy, []string{username, app.formatDatetime(currentTime)})
|
||||
newInv.UsedBy = append(newInv.UsedBy, []string{username, strconv.FormatInt(currentTime.Unix(), 10)})
|
||||
if !del {
|
||||
app.storage.invites[code] = newInv
|
||||
}
|
||||
@ -870,13 +870,25 @@ func (app *appContext) GetInvites(gc *gin.Context) {
|
||||
UserDays: inv.UserDays,
|
||||
UserHours: inv.UserHours,
|
||||
UserMinutes: inv.UserMinutes,
|
||||
Created: app.formatDatetime(inv.Created),
|
||||
Created: inv.Created.Unix(),
|
||||
Profile: inv.Profile,
|
||||
NoLimit: inv.NoLimit,
|
||||
Label: inv.Label,
|
||||
}
|
||||
if len(inv.UsedBy) != 0 {
|
||||
invite.UsedBy = inv.UsedBy
|
||||
invite.UsedBy = map[string]int64{}
|
||||
for _, pair := range inv.UsedBy {
|
||||
// These used to be stored formatted instead of as a unix timestamp.
|
||||
unix, err := strconv.ParseInt(pair[1], 10, 64)
|
||||
if err != nil {
|
||||
date, err := timefmt.Parse(pair[1], app.datePattern+" "+app.timePattern)
|
||||
if err != nil {
|
||||
app.err.Printf("Failed to parse usedBy time: %v", err)
|
||||
}
|
||||
unix = date.Unix()
|
||||
}
|
||||
invite.UsedBy[pair[0]] = unix
|
||||
}
|
||||
}
|
||||
invite.RemainingUses = 1
|
||||
if inv.RemainingUses != 0 {
|
||||
|
6
email.go
6
email.go
@ -19,8 +19,8 @@ import (
|
||||
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
"github.com/itchyny/timefmt-go"
|
||||
jEmail "github.com/jordan-wright/email"
|
||||
"github.com/knz/strtime"
|
||||
"github.com/mailgun/mailgun-go/v4"
|
||||
)
|
||||
|
||||
@ -101,8 +101,8 @@ type Email struct {
|
||||
}
|
||||
|
||||
func (emailer *Emailer) formatExpiry(expiry time.Time, tzaware bool, datePattern, timePattern string) (d, t, expiresIn string) {
|
||||
d, _ = strtime.Strftime(expiry, datePattern)
|
||||
t, _ = strtime.Strftime(expiry, timePattern)
|
||||
d = timefmt.Format(expiry, datePattern)
|
||||
t = timefmt.Format(expiry, timePattern)
|
||||
currentTime := time.Now()
|
||||
if tzaware {
|
||||
currentTime = currentTime.UTC()
|
||||
|
2
go.mod
2
go.mod
@ -26,8 +26,8 @@ require (
|
||||
github.com/hrfee/jfa-go/docs v0.0.0-20201112212552-b6f3cd7c1f71
|
||||
github.com/hrfee/jfa-go/ombi v0.0.0-20201112212552-b6f3cd7c1f71
|
||||
github.com/hrfee/mediabrowser v0.3.3
|
||||
github.com/itchyny/timefmt-go v0.1.2
|
||||
github.com/jordan-wright/email v4.0.1-0.20200917010138-e1c00e156980+incompatible
|
||||
github.com/knz/strtime v0.0.0-20200924090105-187c67f2bf5e
|
||||
github.com/lithammer/shortuuid/v3 v3.0.4
|
||||
github.com/mailgun/mailgun-go/v4 v4.3.0
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -129,6 +129,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hrfee/mediabrowser v0.3.3 h1:7E05uiol8hh2ytKn3WVLrUIvHAyifYEIy3Y5qtuNh8I=
|
||||
github.com/hrfee/mediabrowser v0.3.3/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||
github.com/itchyny/timefmt-go v0.1.2 h1:q0Xa4P5it6K6D7ISsbLAMwx1PnWlixDcJL6/sFs93Hs=
|
||||
github.com/itchyny/timefmt-go v0.1.2/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
|
||||
github.com/jordan-wright/email v4.0.1-0.20200917010138-e1c00e156980+incompatible h1:CL0ooBNfbNyJTJATno+m0h+zM5bW6v7fKlboKUGP/dI=
|
||||
github.com/jordan-wright/email v4.0.1-0.20200917010138-e1c00e156980+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@ -141,8 +143,6 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/knz/strtime v0.0.0-20200924090105-187c67f2bf5e h1:ViPE0JEOvtw5I0EGUiFSr2VNKGNU+3oBT+oHbDXHbxk=
|
||||
github.com/knz/strtime v0.0.0-20200924090105-187c67f2bf5e/go.mod h1:4ZxfWkxwtc7dBeifERVVWRy9F9rTU9p0yCDgeCtlius=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
|
34
models.go
34
models.go
@ -72,23 +72,23 @@ type newProfileDTO struct {
|
||||
}
|
||||
|
||||
type inviteDTO struct {
|
||||
Code string `json:"code" example:"sajdlj23423j23"` // Invite code
|
||||
Days int `json:"days" example:"1"` // Number of days till expiry
|
||||
Hours int `json:"hours" example:"2"` // Number of hours till expiry
|
||||
Minutes int `json:"minutes" example:"3"` // Number of minutes till expiry
|
||||
UserExpiry bool `json:"user-expiry"` // Whether or not user expiry is enabled
|
||||
UserDays int `json:"user-days,omitempty" example:"1"` // Number of days till user expiry
|
||||
UserHours int `json:"user-hours,omitempty" example:"2"` // Number of hours till user expiry
|
||||
UserMinutes int `json:"user-minutes,omitempty" example:"3"` // Number of minutes till user expiry
|
||||
Created string `json:"created" example:"01/01/20 12:00"` // Date of creation
|
||||
Profile string `json:"profile" example:"DefaultProfile"` // Profile used on this invite
|
||||
UsedBy [][]string `json:"used-by,omitempty"` // Users who have used this invite
|
||||
NoLimit bool `json:"no-limit,omitempty"` // If true, invite can be used any number of times
|
||||
RemainingUses int `json:"remaining-uses,omitempty"` // Remaining number of uses (if applicable)
|
||||
Email string `json:"email,omitempty"` // Email the invite was sent to (if applicable)
|
||||
NotifyExpiry bool `json:"notify-expiry,omitempty"` // Whether to notify the requesting user of expiry or not
|
||||
NotifyCreation bool `json:"notify-creation,omitempty"` // Whether to notify the requesting user of account creation or not
|
||||
Label string `json:"label,omitempty" example:"For Friends"` // Optional label for the invite
|
||||
Code string `json:"code" example:"sajdlj23423j23"` // Invite code
|
||||
Days int `json:"days" example:"1"` // Number of days till expiry
|
||||
Hours int `json:"hours" example:"2"` // Number of hours till expiry
|
||||
Minutes int `json:"minutes" example:"3"` // Number of minutes till expiry
|
||||
UserExpiry bool `json:"user-expiry"` // Whether or not user expiry is enabled
|
||||
UserDays int `json:"user-days,omitempty" example:"1"` // Number of days till user expiry
|
||||
UserHours int `json:"user-hours,omitempty" example:"2"` // Number of hours till user expiry
|
||||
UserMinutes int `json:"user-minutes,omitempty" example:"3"` // Number of minutes till user expiry
|
||||
Created int64 `json:"created" example:"1617737207510"` // Date of creation
|
||||
Profile string `json:"profile" example:"DefaultProfile"` // Profile used on this invite
|
||||
UsedBy map[string]int64 `json:"used-by,omitempty"` // Users who have used this invite mapped to their creation time in Epoch/Unix time
|
||||
NoLimit bool `json:"no-limit,omitempty"` // If true, invite can be used any number of times
|
||||
RemainingUses int `json:"remaining-uses,omitempty"` // Remaining number of uses (if applicable)
|
||||
Email string `json:"email,omitempty"` // Email the invite was sent to (if applicable)
|
||||
NotifyExpiry bool `json:"notify-expiry,omitempty"` // Whether to notify the requesting user of expiry or not
|
||||
NotifyCreation bool `json:"notify-creation,omitempty"` // Whether to notify the requesting user of account creation or not
|
||||
Label string `json:"label,omitempty" example:"For Friends"` // Optional label for the invite
|
||||
}
|
||||
|
||||
type getInvitesDTO struct {
|
||||
|
29
storage.go
29
storage.go
@ -59,20 +59,21 @@ type Profile struct {
|
||||
}
|
||||
|
||||
type Invite struct {
|
||||
Created time.Time `json:"created"`
|
||||
NoLimit bool `json:"no-limit"`
|
||||
RemainingUses int `json:"remaining-uses"`
|
||||
ValidTill time.Time `json:"valid_till"`
|
||||
UserExpiry bool `json:"user-duration"`
|
||||
UserDays int `json:"user-days,omitempty"`
|
||||
UserHours int `json:"user-hours,omitempty"`
|
||||
UserMinutes int `json:"user-minutes,omitempty"`
|
||||
Email string `json:"email"`
|
||||
UsedBy [][]string `json:"used-by"`
|
||||
Notify map[string]map[string]bool `json:"notify"`
|
||||
Profile string `json:"profile"`
|
||||
Label string `json:"label,omitempty"`
|
||||
Keys []string `json:"keys,omitempty"`
|
||||
Created time.Time `json:"created"`
|
||||
NoLimit bool `json:"no-limit"`
|
||||
RemainingUses int `json:"remaining-uses"`
|
||||
ValidTill time.Time `json:"valid_till"`
|
||||
UserExpiry bool `json:"user-duration"`
|
||||
UserDays int `json:"user-days,omitempty"`
|
||||
UserHours int `json:"user-hours,omitempty"`
|
||||
UserMinutes int `json:"user-minutes,omitempty"`
|
||||
Email string `json:"email"`
|
||||
// Used to be stored as formatted time, now as Unix.
|
||||
UsedBy [][]string `json:"used-by"`
|
||||
Notify map[string]map[string]bool `json:"notify"`
|
||||
Profile string `json:"profile"`
|
||||
Label string `json:"label,omitempty"`
|
||||
Keys []string `json:"keys,omitempty"`
|
||||
}
|
||||
|
||||
type Lang struct {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { _get, _post, _delete, toClipboard, toggleLoader } from "../modules/common.js";
|
||||
import { _get, _post, _delete, toClipboard, toggleLoader, toDateString } from "../modules/common.js";
|
||||
|
||||
export class DOMInvite implements Invite {
|
||||
updateNotify = (checkbox: HTMLInputElement) => {
|
||||
@ -116,10 +116,9 @@ export class DOMInvite implements Invite {
|
||||
tooltip.textContent = address;
|
||||
}
|
||||
|
||||
private _usedBy: string[][];
|
||||
get usedBy(): string[][] { return this._usedBy; }
|
||||
set usedBy(uB: string[][]) {
|
||||
// ub[i][0]: username, ub[i][1]: date
|
||||
private _usedBy: { [name: string]: number };
|
||||
get usedBy(): { [name: string]: number } { return this._usedBy; }
|
||||
set usedBy(uB: { [name: string]: number }) {
|
||||
this._usedBy = uB;
|
||||
if (uB.length == 0) {
|
||||
this._right.classList.add("empty");
|
||||
@ -137,11 +136,11 @@ export class DOMInvite implements Invite {
|
||||
</thead>
|
||||
<tbody>
|
||||
`;
|
||||
for (let user of uB) {
|
||||
for (let username in uB) {
|
||||
innerHTML += `
|
||||
<tr>
|
||||
<td>${user[0]}</td>
|
||||
<td>${user[1]}</td>
|
||||
<td>${username}</td>
|
||||
<td>${toDateString(new Date(uB[username] * 1000))}</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
@ -152,11 +151,16 @@ export class DOMInvite implements Invite {
|
||||
this._userTable.innerHTML = innerHTML;
|
||||
}
|
||||
|
||||
private _created: string;
|
||||
get created(): string { return this._created; }
|
||||
set created(created: string) {
|
||||
this._created = created;
|
||||
this._middle.querySelector("strong.inv-created").textContent = created;
|
||||
private _createdUnix: number;
|
||||
get created(): number { return this._createdUnix; }
|
||||
set created(unix: number) {
|
||||
this._createdUnix = unix;
|
||||
const el = this._middle.querySelector("strong.inv-created");
|
||||
if (unix == 0) {
|
||||
el.textContent = "n/a";
|
||||
} else {
|
||||
el.textContent = toDateString(new Date(unix*1000));
|
||||
}
|
||||
}
|
||||
|
||||
private _notifyExpiry: boolean = false;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { _get, _post, toggleLoader } from "../modules/common.js";
|
||||
import { _get, _post, toggleLoader, toDateString } from "../modules/common.js";
|
||||
import { Marked, Renderer } from "@ts-stack/markdown";
|
||||
|
||||
interface updateDTO {
|
||||
@ -29,7 +29,7 @@ export class Updater implements updater {
|
||||
get date(): number { return Math.floor(this._date.getTime() / 1000); }
|
||||
set date(unix: number) {
|
||||
this._date = new Date(unix * 1000);
|
||||
document.getElementById("update-date").textContent = this._date.toDateString() + " " + this._date.toLocaleTimeString();
|
||||
document.getElementById("update-date").textContent = toDateString(this._date);
|
||||
}
|
||||
|
||||
get description(): string { return this._update.description; }
|
||||
|
@ -104,8 +104,8 @@ interface Invite {
|
||||
expiresIn?: string;
|
||||
remainingUses?: string;
|
||||
email?: string;
|
||||
usedBy?: string[][];
|
||||
created?: string;
|
||||
usedBy?: { [name: string]: number };
|
||||
created?: number;
|
||||
notifyExpiry?: boolean;
|
||||
notifyCreation?: boolean;
|
||||
profile?: string;
|
||||
|
Loading…
Reference in New Issue
Block a user