diff --git a/api.go b/api.go index 063d1f7..73a1e94 100644 --- a/api.go +++ b/api.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "strconv" "strings" "time" @@ -399,7 +400,13 @@ func (app *appContext) GenerateInvite(gc *gin.Context) { current_time := time.Now() 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)) + // make sure code doesn't begin with number 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 invite.Created = current_time if req.MultipleUses { @@ -449,7 +456,8 @@ func (app *appContext) SetProfile(gc *gin.Context) { var req profileReq gc.BindJSON(&req) 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) respond(500, "Profile not found", gc) return diff --git a/data/templates/admin.html b/data/templates/admin.html index 7b7e876..f97d023 100644 --- a/data/templates/admin.html +++ b/data/templates/admin.html @@ -365,6 +365,11 @@ +
+ + +
{{ if .email_enabled }}
diff --git a/main.go b/main.go index 607ab3f..0622ba6 100644 --- a/main.go +++ b/main.go @@ -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) { app.info.Println("Migrating user template files to new profile format") 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 .old.json") app.storage.storeProfiles() } diff --git a/ts/invites.ts b/ts/invites.ts index 3a0f654..0b2b16c 100644 --- a/ts/invites.ts +++ b/ts/invites.ts @@ -142,19 +142,15 @@ function addItem(invite: Invite): void { let profiles = ` `; let dateCreated: string; @@ -209,7 +205,7 @@ function addItem(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"); if (remainingUses) { remainingUses.textContent = `Remaining uses: ${invite.remainingUses}`; @@ -237,6 +233,18 @@ function generateInvites(empty?: boolean): void { if (this.readyState == 4) { let data = this.response; 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 += ` + + `; + } + innerHTML += ` + + `; + Profiles.innerHTML = innerHTML; if (data['invites'] == null || data['invites'].length == 0) { document.getElementById('invites').textContent = ''; addItem(emptyInvite()); @@ -311,6 +319,9 @@ fixCheckboxes(); if (!send['multiple-uses'] || send['no-limit']) { delete send['remaining-uses']; } + if (send["profile"] == "NoProfile") { + send["profile"] = ""; + } const sendToAddress: any = document.getElementById('send_to_address'); const sendToAddressEnabled: any = document.getElementById('send_to_address_enabled'); if (sendToAddress && sendToAddressEnabled) { @@ -318,6 +329,7 @@ fixCheckboxes(); delete send['send_to_address']; delete send['send_to_address_enabled']; } + console.log(send); _post("/generateInvite", send, function (): void { if (this.readyState == 4) { button.textContent = 'Generate'; @@ -334,10 +346,14 @@ function setProfile(select: HTMLSelectElement): void { if (!select.value) { return; } + let val = select.value; + if (select.value == "NoProfile") { + val = "" + } const invite = select.id.replace("profile_", ""); const send = { "invite": invite, - "profile": select.value + "profile": val }; _post("/setProfile", send, function (): void { if (this.readyState == 4 && this.status != 200) { diff --git a/ts/serialize.ts b/ts/serialize.ts index e622a8b..4f8c165 100644 --- a/ts/serialize.ts +++ b/ts/serialize.ts @@ -22,11 +22,12 @@ function serializeForm(id: string): Object { break; case "select-one": case "select": - let val: string | number = (el as HTMLSelectElement).value; - if (+val != NaN) { - val = +val; + let val: string = (el as HTMLSelectElement).value.toString(); + if (!isNaN(val as any)) { + formData[name] = +val; + } else { + formData[name] = val; } - formData[name] = val; break; } }