mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
add months field to invites & expiry
This commit is contained in:
parent
a8f71c83da
commit
d701c5f27d
13
api.go
13
api.go
@ -438,7 +438,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
||||
if invite.UserExpiry {
|
||||
app.storage.usersLock.Lock()
|
||||
defer app.storage.usersLock.Unlock()
|
||||
expiry = time.Now().Add(time.Duration(60*(invite.UserDays*24+invite.UserHours)+invite.UserMinutes) * time.Minute)
|
||||
expiry = time.Now().AddDate(0, invite.UserMonths, invite.UserDays).Add(time.Duration((60*invite.UserHours)+invite.UserMinutes) * time.Minute)
|
||||
app.storage.users[id] = expiry
|
||||
if err := app.storage.storeUsers(); err != nil {
|
||||
app.err.Printf("Failed to store user duration: %v", err)
|
||||
@ -472,7 +472,7 @@ func (app *appContext) ExtendExpiry(gc *gin.Context) {
|
||||
var req extendExpiryDTO
|
||||
gc.BindJSON(&req)
|
||||
app.info.Printf("Expiry extension requested for %d user(s)", len(req.Users))
|
||||
if req.Days <= 0 && req.Hours <= 0 && req.Minutes <= 0 {
|
||||
if req.Months <= 0 && req.Days <= 0 && req.Hours <= 0 && req.Minutes <= 0 {
|
||||
respondBool(400, false, gc)
|
||||
return
|
||||
}
|
||||
@ -480,7 +480,7 @@ func (app *appContext) ExtendExpiry(gc *gin.Context) {
|
||||
defer app.storage.usersLock.Unlock()
|
||||
for _, id := range req.Users {
|
||||
if expiry, ok := app.storage.users[id]; ok {
|
||||
app.storage.users[id] = expiry.Add(time.Duration(60*(req.Days*24+req.Hours)+req.Minutes) * time.Minute)
|
||||
app.storage.users[id] = expiry.AddDate(0, req.Months, req.Days).Add(time.Duration(((60 * req.Hours) + req.Minutes)) * time.Minute)
|
||||
app.debug.Printf("Expiry extended for \"%s\"", id)
|
||||
}
|
||||
}
|
||||
@ -654,7 +654,7 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
|
||||
app.storage.loadInvites()
|
||||
gc.BindJSON(&req)
|
||||
currentTime := time.Now()
|
||||
validTill := currentTime.AddDate(0, 0, req.Days)
|
||||
validTill := currentTime.AddDate(0, req.Months, req.Days)
|
||||
validTill = validTill.Add(time.Hour*time.Duration(req.Hours) + time.Minute*time.Duration(req.Minutes))
|
||||
// make sure code doesn't begin with number
|
||||
inviteCode := shortuuid.New()
|
||||
@ -679,6 +679,7 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
|
||||
}
|
||||
invite.UserExpiry = req.UserExpiry
|
||||
if invite.UserExpiry {
|
||||
invite.UserMonths = req.UserMonths
|
||||
invite.UserDays = req.UserDays
|
||||
invite.UserHours = req.UserHours
|
||||
invite.UserMinutes = req.UserMinutes
|
||||
@ -861,13 +862,15 @@ func (app *appContext) GetInvites(gc *gin.Context) {
|
||||
app.checkInvites()
|
||||
var invites []inviteDTO
|
||||
for code, inv := range app.storage.invites {
|
||||
_, _, days, hours, minutes, _ := timeDiff(inv.ValidTill, currentTime)
|
||||
_, months, days, hours, minutes, _ := timeDiff(inv.ValidTill, currentTime)
|
||||
invite := inviteDTO{
|
||||
Code: code,
|
||||
Months: months,
|
||||
Days: days,
|
||||
Hours: hours,
|
||||
Minutes: minutes,
|
||||
UserExpiry: inv.UserExpiry,
|
||||
UserMonths: inv.UserMonths,
|
||||
UserDays: inv.UserDays,
|
||||
UserHours: inv.UserHours,
|
||||
UserMinutes: inv.UserMinutes,
|
||||
|
@ -124,7 +124,7 @@
|
||||
["en-us", "English (US)"]
|
||||
],
|
||||
"value": "en-us",
|
||||
"description": "Default Account Form Language. See issue #12 on Github if you'd like to translate."
|
||||
"description": "Default Account Form Language. Visit weblate.hrfee.dev if you'd like to translate."
|
||||
},
|
||||
"language-admin": {
|
||||
"name": "Default Admin Language",
|
||||
@ -135,7 +135,7 @@
|
||||
["en-us", "English (US)"]
|
||||
],
|
||||
"value": "en-us",
|
||||
"description": "Default Admin page Language. Settings has not been translated. Submit a PR on github if you'd like to translate."
|
||||
"description": "Default Admin page Language. Settings has not been translated. Visit weblate.hrfee.dev if you'd like to translate."
|
||||
},
|
||||
"theme": {
|
||||
"name": "Default Look",
|
||||
|
@ -99,24 +99,42 @@
|
||||
<form class="modal-content card" id="form-extend-expiry" href="">
|
||||
<span class="heading"><span id="header-extend-expiry"></span> <span class="modal-close">×</span></span>
|
||||
<div class="content mt-half">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label class="label supra" for="extend-expiry-months">{{ .strings.inviteMonths }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="extend-expiry-months">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="extend-expiry-days">{{ .strings.inviteDays }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="extend-expiry-days">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label class="label supra" for="extend-expiry-hours">{{ .strings.inviteHours }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="extend-expiry-hours">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="extend-expiry-minutes">{{ .strings.inviteMinutes }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="extend-expiry-minutes">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label>
|
||||
<input type="submit" class="unfocused">
|
||||
<span class="button ~critical !normal full-width center supra submit">{{ .strings.submit }}</span>
|
||||
@ -325,18 +343,34 @@
|
||||
</label>
|
||||
</div>
|
||||
<div id="inv-duration">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label class="label supra" for="create-months">{{ .strings.inviteMonths }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="create-months">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="create-days">{{ .strings.inviteDays }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="create-days">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label class="label supra" for="create-hours">{{ .strings.inviteHours }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="create-hours">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="create-minutes">{{ .strings.inviteMinutes }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="create-minutes">
|
||||
@ -344,6 +378,8 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="user-expiry" class="unfocused">
|
||||
<p class="support">{{ .strings.userExpiryDescription }}</p>
|
||||
<div class="mb-half">
|
||||
@ -352,18 +388,34 @@
|
||||
<span class="ml-half">{{ .strings.enabled }} </span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label class="label supra" for="user-months">{{ .strings.inviteMonths }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="user-months">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="user-days">{{ .strings.inviteDays }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="user-days">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label class="label supra" for="user-hours">{{ .strings.inviteHours }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="user-hours">
|
||||
<option>0</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="user-minutes">{{ .strings.inviteMinutes }}</label>
|
||||
<div class="select ~neutral !normal mb-1 mt-half">
|
||||
<select id="user-minutes">
|
||||
@ -371,9 +423,13 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="label supra" for="create-label"> {{ .strings.label }}</label>
|
||||
<input type="text" id="create-label" class="input ~neutral !normal mb-1 mt-half">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card ~neutral !normal col">
|
||||
<label class="label supra" for="create-uses">{{ .strings.inviteNumberOfUses }}</label>
|
||||
<div class="flex-expand mb-1 mt-half">
|
||||
|
@ -9,6 +9,7 @@
|
||||
window.messages = JSON.parse({{ .notifications }});
|
||||
window.confirmation = {{ .confirmation }};
|
||||
window.userExpiryEnabled = {{ .userExpiry }};
|
||||
window.userExpiryMonths = {{ .userExpiryMonths }};
|
||||
window.userExpiryDays = {{ .userExpiryDays }};
|
||||
window.userExpiryHours = {{ .userExpiryHours }};
|
||||
window.userExpiryMinutes = {{ .userExpiryMinutes }};
|
||||
|
@ -6,6 +6,7 @@
|
||||
"invites": "Invites",
|
||||
"accounts": "Accounts",
|
||||
"settings": "Settings",
|
||||
"inviteMonths": "Months",
|
||||
"inviteDays": "Days",
|
||||
"inviteHours": "Hours",
|
||||
"inviteMinutes": "Minutes",
|
||||
|
@ -7,6 +7,7 @@
|
||||
"invites": "Invitations",
|
||||
"accounts": "Comptes",
|
||||
"settings": "Réglages",
|
||||
"inviteMonths": "Mois",
|
||||
"inviteDays": "Jours",
|
||||
"inviteHours": "Heures",
|
||||
"inviteMinutes": "Minutes",
|
||||
|
@ -30,10 +30,12 @@ type deleteUserDTO struct {
|
||||
}
|
||||
|
||||
type generateInviteDTO struct {
|
||||
Months int `json:"months" example:"0"` // Number of months
|
||||
Days int `json:"days" example:"1"` // Number of days
|
||||
Hours int `json:"hours" example:"2"` // Number of hours
|
||||
Minutes int `json:"minutes" example:"3"` // Number of minutes
|
||||
UserExpiry bool `json:"user-expiry"` // Whether or not user expiry is enabled
|
||||
UserMonths int `json:"user-months,omitempty" example:"1"` // Number of months till user expiry
|
||||
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
|
||||
@ -73,10 +75,12 @@ type newProfileDTO struct {
|
||||
|
||||
type inviteDTO struct {
|
||||
Code string `json:"code" example:"sajdlj23423j23"` // Invite code
|
||||
Months int `json:"months" example:"1"` // Number of months till expiry
|
||||
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
|
||||
UserMonths int `json:"user-months,omitempty" example:"1"` // Number of months till user expiry
|
||||
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
|
||||
@ -212,6 +216,7 @@ type customEmailDTO struct {
|
||||
|
||||
type extendExpiryDTO struct {
|
||||
Users []string `json:"users"` // List of user IDs to apply to.
|
||||
Months int `json:"months" example:"1"` // Number of months to add.
|
||||
Days int `json:"days" example:"1"` // Number of days to add.
|
||||
Hours int `json:"hours" example:"2"` // Number of hours to add.
|
||||
Minutes int `json:"minutes" example:"3"` // Number of minutes to add.
|
||||
|
@ -64,6 +64,7 @@ type Invite struct {
|
||||
RemainingUses int `json:"remaining-uses"`
|
||||
ValidTill time.Time `json:"valid_till"`
|
||||
UserExpiry bool `json:"user-duration"`
|
||||
UserMonths int `json:"user-months,omitempty"`
|
||||
UserDays int `json:"user-days,omitempty"`
|
||||
UserHours int `json:"user-hours,omitempty"`
|
||||
UserMinutes int `json:"user-minutes,omitempty"`
|
||||
|
@ -11,6 +11,7 @@ interface formWindow extends Window {
|
||||
confirmation: boolean;
|
||||
confirmationModal: Modal
|
||||
userExpiryEnabled: boolean;
|
||||
userExpiryMonths: number;
|
||||
userExpiryDays: number;
|
||||
userExpiryHours: number;
|
||||
userExpiryMinutes: number;
|
||||
@ -43,6 +44,7 @@ if (window.userExpiryEnabled) {
|
||||
const messageEl = document.getElementById("user-expiry-message") as HTMLElement;
|
||||
const calculateTime = () => {
|
||||
let time = new Date()
|
||||
time.setMonth(time.getMonth() + window.userExpiryMonths);
|
||||
time.setDate(time.getDate() + window.userExpiryDays);
|
||||
time.setHours(time.getHours() + window.userExpiryHours);
|
||||
time.setMinutes(time.getMinutes() + window.userExpiryMinutes);
|
||||
|
@ -217,7 +217,7 @@ export class accountsList {
|
||||
|
||||
private _count = 30;
|
||||
private _populateNumbers = () => {
|
||||
const fieldIDs = ["days", "hours", "minutes"];
|
||||
const fieldIDs = ["months", "days", "hours", "minutes"];
|
||||
const prefixes = ["extend-expiry-"];
|
||||
for (let i = 0; i < fieldIDs.length; i++) {
|
||||
for (let j = 0; j < prefixes.length; j++) {
|
||||
@ -560,7 +560,7 @@ export class accountsList {
|
||||
form.onsubmit = (event: Event) => {
|
||||
event.preventDefault();
|
||||
let send = { "users": applyList }
|
||||
for (let field of ["days", "hours", "minutes"]) {
|
||||
for (let field of ["months", "days", "hours", "minutes"]) {
|
||||
send[field] = +(document.getElementById("extend-expiry-"+field) as HTMLSelectElement).value;
|
||||
}
|
||||
_post("/users/extend", send, (req: XMLHttpRequest) => {
|
||||
|
@ -486,13 +486,17 @@ function parseInvite(invite: { [f: string]: string | number | string[][] | boole
|
||||
parsed.label = invite["label"] as string || "";
|
||||
let time = "";
|
||||
let userExpiryTime = "";
|
||||
const fields = ["days", "hours", "minutes"];
|
||||
const fields = ["months", "days", "hours", "minutes"];
|
||||
let prefixes = [""];
|
||||
if (invite["user-expiry"] as boolean) { prefixes.push("user-"); }
|
||||
for (let i = 0; i < fields.length; i++) {
|
||||
for (let j = 0; j < prefixes.length; j++) {
|
||||
if (invite[prefixes[j]+fields[i]]) {
|
||||
let text = `${invite[prefixes[j]+fields[i]]}${fields[i][0]} `;
|
||||
let abbreviation = fields[i][0];
|
||||
if (fields[i] == "months") {
|
||||
abbreviation += fields[i][1];
|
||||
}
|
||||
let text = `${invite[prefixes[j]+fields[i]]}${abbreviation} `;
|
||||
if (prefixes[j] == "user-") {
|
||||
userExpiryTime += text;
|
||||
} else {
|
||||
@ -524,9 +528,11 @@ export class createInvite {
|
||||
private _profile = document.getElementById("create-profile") as HTMLSelectElement;
|
||||
private _label = document.getElementById("create-label") as HTMLInputElement;
|
||||
|
||||
private _months = document.getElementById("create-months") as HTMLSelectElement;
|
||||
private _days = document.getElementById("create-days") as HTMLSelectElement;
|
||||
private _hours = document.getElementById("create-hours") as HTMLSelectElement;
|
||||
private _minutes = document.getElementById("create-minutes") as HTMLSelectElement;
|
||||
private _userMonths = document.getElementById("user-months") as HTMLSelectElement;
|
||||
private _userDays = document.getElementById("user-days") as HTMLSelectElement;
|
||||
private _userHours = document.getElementById("user-hours") as HTMLSelectElement;
|
||||
private _userMinutes = document.getElementById("user-minutes") as HTMLSelectElement;
|
||||
@ -542,7 +548,7 @@ export class createInvite {
|
||||
|
||||
private _count: Number = 30;
|
||||
private _populateNumbers = () => {
|
||||
const fieldIDs = ["days", "hours", "minutes"];
|
||||
const fieldIDs = ["months", "days", "hours", "minutes"];
|
||||
const prefixes = ["create-", "user-"];
|
||||
for (let i = 0; i < fieldIDs.length; i++) {
|
||||
for (let j = 0; j < prefixes.length; j++) {
|
||||
@ -597,7 +603,7 @@ export class createInvite {
|
||||
set uses(n: number) { this._uses.valueAsNumber = n; }
|
||||
|
||||
private _checkDurationValidity = () => {
|
||||
if (this.days + this.hours + this.minutes == 0) {
|
||||
if (this.months + this.days + this.hours + this.minutes == 0) {
|
||||
this._createButton.setAttribute("disabled", "");
|
||||
this._createButton.onclick = null;
|
||||
} else {
|
||||
@ -606,6 +612,13 @@ export class createInvite {
|
||||
}
|
||||
}
|
||||
|
||||
get months(): number {
|
||||
return +this._months.value;
|
||||
}
|
||||
set months(n: number) {
|
||||
this._months.value = ""+n;
|
||||
this._checkDurationValidity();
|
||||
}
|
||||
get days(): number {
|
||||
return +this._days.value;
|
||||
}
|
||||
@ -640,10 +653,17 @@ export class createInvite {
|
||||
parent.classList.add("~neutral");
|
||||
parent.classList.remove("~urge");
|
||||
}
|
||||
this._userMonths.disabled = !enabled;
|
||||
this._userDays.disabled = !enabled;
|
||||
this._userHours.disabled = !enabled;
|
||||
this._userMinutes.disabled = !enabled;
|
||||
}
|
||||
get userMonths(): number {
|
||||
return +this._userMonths.value;
|
||||
}
|
||||
set userMonths(n: number) {
|
||||
this._userMonths.value = ""+n;
|
||||
}
|
||||
get userDays(): number {
|
||||
return +this._userDays.value;
|
||||
}
|
||||
@ -700,10 +720,12 @@ export class createInvite {
|
||||
userExpiry = false;
|
||||
}
|
||||
let send = {
|
||||
"months": this.months,
|
||||
"days": this.days,
|
||||
"hours": this.hours,
|
||||
"minutes": this.minutes,
|
||||
"user-expiry": userExpiry,
|
||||
"user-months": this.userMonths,
|
||||
"user-days": this.userDays,
|
||||
"user-hours": this.userHours,
|
||||
"user-minutes": this.userMinutes,
|
||||
@ -726,6 +748,7 @@ export class createInvite {
|
||||
|
||||
constructor() {
|
||||
this._populateNumbers();
|
||||
this.months = 0;
|
||||
this.days = 0;
|
||||
this.hours = 0;
|
||||
this.minutes = 30;
|
||||
@ -734,6 +757,7 @@ export class createInvite {
|
||||
this._sendToEnabled.onchange = () => { this.sendToEnabled = this.sendToEnabled; };
|
||||
this.userExpiry = false;
|
||||
this._userExpiryToggle.onchange = () => { this.userExpiry = this._userExpiryToggle.checked; }
|
||||
this._userMonths.disabled = true;
|
||||
this._userDays.disabled = true;
|
||||
this._userHours.disabled = true;
|
||||
this._userMinutes.disabled = true;
|
||||
|
1
views.go
1
views.go
@ -254,6 +254,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
|
||||
"code": code,
|
||||
"confirmation": app.config.Section("email_confirmation").Key("enabled").MustBool(false),
|
||||
"userExpiry": inv.UserExpiry,
|
||||
"userExpiryMonths": inv.UserMonths,
|
||||
"userExpiryDays": inv.UserDays,
|
||||
"userExpiryHours": inv.UserHours,
|
||||
"userExpiryMinutes": inv.UserMinutes,
|
||||
|
Loading…
Reference in New Issue
Block a user