1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-06-02 23:57:46 +02:00

Fix bug with invites in webui, add profile selector

invite codes starting with a digit don't work with the webui, so
GenerateInvite regenerates uuids until theres one that doesn't.
This commit is contained in:
Harvey Tindall 2020-09-22 00:34:11 +01:00
parent 32b8ed4aa2
commit b6ceee508c
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
5 changed files with 53 additions and 12 deletions

10
api.go
View File

@ -3,6 +3,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strconv"
"strings" "strings"
"time" "time"
@ -399,7 +400,13 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
current_time := time.Now() current_time := time.Now()
valid_till := current_time.AddDate(0, 0, req.Days) valid_till := current_time.AddDate(0, 0, req.Days)
valid_till = valid_till.Add(time.Hour*time.Duration(req.Hours) + time.Minute*time.Duration(req.Minutes)) valid_till = valid_till.Add(time.Hour*time.Duration(req.Hours) + time.Minute*time.Duration(req.Minutes))
// make sure code doesn't begin with number
invite_code := shortuuid.New() invite_code := shortuuid.New()
_, err := strconv.Atoi(string(invite_code[0]))
for err == nil {
invite_code = shortuuid.New()
_, err = strconv.Atoi(string(invite_code[0]))
}
var invite Invite var invite Invite
invite.Created = current_time invite.Created = current_time
if req.MultipleUses { if req.MultipleUses {
@ -449,7 +456,8 @@ func (app *appContext) SetProfile(gc *gin.Context) {
var req profileReq var req profileReq
gc.BindJSON(&req) gc.BindJSON(&req)
app.debug.Printf("%s: Setting profile to \"%s\"", req.Invite, req.Profile) app.debug.Printf("%s: Setting profile to \"%s\"", req.Invite, req.Profile)
if _, ok := app.storage.profiles[req.Profile]; !ok { // "" means "Don't apply profile"
if _, ok := app.storage.profiles[req.Profile]; !ok && req.Profile != "" {
app.err.Printf("%s: Profile \"%s\" not found", req.Invite, req.Profile) app.err.Printf("%s: Profile \"%s\" not found", req.Invite, req.Profile)
respond(500, "Profile not found", gc) respond(500, "Profile not found", gc)
return return

View File

@ -365,6 +365,11 @@
</label> </label>
<div id="noLimitWarning" class="form-text" style="display: none;">Warning: Unlimited usage invites pose a risk if published online.</div> <div id="noLimitWarning" class="form-text" style="display: none;">Warning: Unlimited usage invites pose a risk if published online.</div>
</div> </div>
<div class="form-group" style="margin-bottom: 1rem;">
<label for="inviteProfile">Account creation profile</label>
<select class="form-control form-select" id="inviteProfile" name="profile">
</select>
</div>
{{ if .email_enabled }} {{ if .email_enabled }}
<div class="form-group"> <div class="form-group">
<label for="send_to_address">Send invite to address</label> <label for="send_to_address">Send invite to address</label>

11
main.go
View File

@ -334,6 +334,17 @@ func start(asDaemon, firstCall bool) {
if !(len(app.storage.policy) == 0 && len(app.storage.configuration) == 0 && len(app.storage.displayprefs) == 0) { if !(len(app.storage.policy) == 0 && len(app.storage.configuration) == 0 && len(app.storage.displayprefs) == 0) {
app.info.Println("Migrating user template files to new profile format") app.info.Println("Migrating user template files to new profile format")
app.storage.migrateToProfile() app.storage.migrateToProfile()
for _, path := range [3]string{app.storage.policy_path, app.storage.configuration_path, app.storage.displayprefs_path} {
if _, err := os.Stat(path); !os.IsNotExist(err) {
dir, fname := filepath.Split(path)
newFname := strings.Replace(fname, ".json", ".old.json", 1)
err := os.Rename(path, filepath.Join(dir, newFname))
if err != nil {
app.err.Fatalf("Failed to rename %s: %s", fname, err)
}
}
}
app.info.Println("In case of a problem, your original files have been renamed to <file>.old.json")
app.storage.storeProfiles() app.storage.storeProfiles()
} }

View File

@ -142,19 +142,15 @@ function addItem(invite: Invite): void {
let profiles = ` let profiles = `
<label class="input-group-text" for="profile_${CSS.escape(invite.code)}">Profile: </label> <label class="input-group-text" for="profile_${CSS.escape(invite.code)}">Profile: </label>
<select class="form-select" id="profile_${CSS.escape(invite.code)}" onchange="setProfile(this)"> <select class="form-select" id="profile_${CSS.escape(invite.code)}" onchange="setProfile(this)">
<option value="NoProfile" selected>No Profile</option>
`; `;
let match = false;
for (const i in availableProfiles) { for (const i in availableProfiles) {
let selected = ""; let selected = "";
if (availableProfiles[i] == invite.profile) { if (availableProfiles[i] == invite.profile) {
selected = "selected"; selected = "selected";
match = true;
} }
profiles += `<option value="${availableProfiles[i]}" ${selected}>${availableProfiles[i]}</option>`; profiles += `<option value="${availableProfiles[i]}" ${selected}>${availableProfiles[i]}</option>`;
} }
if (!match) {
profiles += `<option value="" selected></option>`;
}
profiles += `</select>`; profiles += `</select>`;
let dateCreated: string; let dateCreated: string;
@ -209,7 +205,7 @@ function addItem(invite: Invite): void {
} }
function updateInvite(invite: Invite): void { function updateInvite(invite: Invite): void {
document.getElementById(CSS.escape(invite.code) + "_expiry").textContent = invite.expiresIn; document.getElementById(invite.code + "_expiry").textContent = invite.expiresIn;
const remainingUses: any = document.getElementById(CSS.escape(invite.code) + "_remainingUses"); const remainingUses: any = document.getElementById(CSS.escape(invite.code) + "_remainingUses");
if (remainingUses) { if (remainingUses) {
remainingUses.textContent = `Remaining uses: ${invite.remainingUses}`; remainingUses.textContent = `Remaining uses: ${invite.remainingUses}`;
@ -237,6 +233,18 @@ function generateInvites(empty?: boolean): void {
if (this.readyState == 4) { if (this.readyState == 4) {
let data = this.response; let data = this.response;
availableProfiles = data['profiles']; availableProfiles = data['profiles'];
const Profiles = document.getElementById('inviteProfile') as HTMLSelectElement;
let innerHTML = "";
for (let i = 0; i < availableProfiles.length; i++) {
const profile = availableProfiles[i];
innerHTML += `
<option value="${profile}" ${(i == 0) ? "selected" : ""}>${profile}</option>
`;
}
innerHTML += `
<option value="NoProfile" ${(availableProfiles.length == 0) ? "selected" : ""}>No Profile</option>
`;
Profiles.innerHTML = innerHTML;
if (data['invites'] == null || data['invites'].length == 0) { if (data['invites'] == null || data['invites'].length == 0) {
document.getElementById('invites').textContent = ''; document.getElementById('invites').textContent = '';
addItem(emptyInvite()); addItem(emptyInvite());
@ -311,6 +319,9 @@ fixCheckboxes();
if (!send['multiple-uses'] || send['no-limit']) { if (!send['multiple-uses'] || send['no-limit']) {
delete send['remaining-uses']; delete send['remaining-uses'];
} }
if (send["profile"] == "NoProfile") {
send["profile"] = "";
}
const sendToAddress: any = document.getElementById('send_to_address'); const sendToAddress: any = document.getElementById('send_to_address');
const sendToAddressEnabled: any = document.getElementById('send_to_address_enabled'); const sendToAddressEnabled: any = document.getElementById('send_to_address_enabled');
if (sendToAddress && sendToAddressEnabled) { if (sendToAddress && sendToAddressEnabled) {
@ -318,6 +329,7 @@ fixCheckboxes();
delete send['send_to_address']; delete send['send_to_address'];
delete send['send_to_address_enabled']; delete send['send_to_address_enabled'];
} }
console.log(send);
_post("/generateInvite", send, function (): void { _post("/generateInvite", send, function (): void {
if (this.readyState == 4) { if (this.readyState == 4) {
button.textContent = 'Generate'; button.textContent = 'Generate';
@ -334,10 +346,14 @@ function setProfile(select: HTMLSelectElement): void {
if (!select.value) { if (!select.value) {
return; return;
} }
let val = select.value;
if (select.value == "NoProfile") {
val = ""
}
const invite = select.id.replace("profile_", ""); const invite = select.id.replace("profile_", "");
const send = { const send = {
"invite": invite, "invite": invite,
"profile": select.value "profile": val
}; };
_post("/setProfile", send, function (): void { _post("/setProfile", send, function (): void {
if (this.readyState == 4 && this.status != 200) { if (this.readyState == 4 && this.status != 200) {

View File

@ -22,11 +22,12 @@ function serializeForm(id: string): Object {
break; break;
case "select-one": case "select-one":
case "select": case "select":
let val: string | number = (el as HTMLSelectElement).value; let val: string = (el as HTMLSelectElement).value.toString();
if (+val != NaN) { if (!isNaN(val as any)) {
val = +val; formData[name] = +val;
} else {
formData[name] = val;
} }
formData[name] = val;
break; break;
} }
} }