mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-28 03:50:10 +00:00
Compare commits
3 Commits
82d07e423c
...
2d6b1717db
Author | SHA1 | Date | |
---|---|---|---|
2d6b1717db | |||
9abb177427 | |||
2f9965bcda |
@ -465,7 +465,7 @@
|
|||||||
<p>{{ .contactMessage }}</p>
|
<p>{{ .contactMessage }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="serialize.js"></script>
|
<script src="common.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var availableProfiles = [];
|
var availableProfiles = [];
|
||||||
{{ if .notifications }}
|
{{ if .notifications }}
|
||||||
|
@ -102,8 +102,8 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{{ range $key, $value := .requirements }}
|
{{ range $key, $value := .requirements }}
|
||||||
<li id="{{ $key }}" class="list-group-item list-group-item-danger">
|
<li id="{{ $key }}" min="{{ $value }}" class="list-group-item list-group-item-danger">
|
||||||
<div> {{ $value }}</div>
|
<div></div>
|
||||||
</li>
|
</li>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</ul>
|
</ul>
|
||||||
@ -114,109 +114,32 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="serialize.js"></script>
|
<script src="common.js"></script>
|
||||||
<script>
|
<script>
|
||||||
{{ if .bs5 }}
|
var usernameEnabled = {{ .username }}
|
||||||
var bsVersion = 5;
|
var validationStrings = {
|
||||||
{{ else }}
|
"length": {
|
||||||
var bsVersion = 4;
|
"singular": "Must have at least {n} character",
|
||||||
{{ end }}
|
"plural": "Must have a least {n} characters"
|
||||||
if (bsVersion == 5) {
|
},
|
||||||
var successBox = new bootstrap.Modal(document.getElementById('successBox'));
|
"uppercase": {
|
||||||
} else if (bsVersion == 4) {
|
"singular": "Must have at least {n} uppercase character",
|
||||||
var successBox = {
|
"plural": "Must have at least {n} uppercase characters"
|
||||||
show : function() {
|
},
|
||||||
return $('#successBox').modal('show');
|
"lowercase": {
|
||||||
},
|
"singular": "Must have at least {n} lowercase character",
|
||||||
hide : function() {
|
"plural": "Must have at least {n} lowercase characters"
|
||||||
return $('#successBox').modal('hide');
|
},
|
||||||
}
|
"number": {
|
||||||
};
|
"singular": "Must have at least {n} number",
|
||||||
};
|
"plural": "Must have at least {n} numbers"
|
||||||
var code = window.location.href.split('/').pop();
|
},
|
||||||
function toggleSpinner () {
|
"special": {
|
||||||
var submitButton = document.getElementById('submitButton');
|
"singular": "Must have at least {n} special character",
|
||||||
var oldSpan = document.getElementById('createAccount');
|
"plural": "Must have at least {n} special characters"
|
||||||
var newSpan = document.createElement('span');
|
|
||||||
newSpan.id = 'createAccount';
|
|
||||||
if (document.getElementById('createAccountSpinner')) {
|
|
||||||
newSpan.appendChild(document.createTextNode('Create Account'));
|
|
||||||
submitButton.disabled = false;
|
|
||||||
} else {
|
|
||||||
var spinner = document.createElement('span');
|
|
||||||
spinner.id = 'createAccountSpinner';
|
|
||||||
spinner.classList.add('spinner-border', 'spinner-border-sm');
|
|
||||||
spinner.setAttribute('role', 'status');
|
|
||||||
spinner.setAttribute('aria-hidden', 'true');
|
|
||||||
var text = document.createTextNode(' Creating...');
|
|
||||||
newSpan.appendChild(spinner);
|
|
||||||
newSpan.appendChild(text);
|
|
||||||
submitButton.disabled = true;
|
|
||||||
}
|
}
|
||||||
submitButton.replaceChild(newSpan, oldSpan);
|
}
|
||||||
};
|
|
||||||
document.getElementById('accountForm').onsubmit = function() {
|
|
||||||
if (document.getElementById('errorMessage')) {
|
|
||||||
document.getElementById('errorMessage').remove();
|
|
||||||
}
|
|
||||||
toggleSpinner();
|
|
||||||
var send = serializeForm('accountForm');
|
|
||||||
send['code'] = code;
|
|
||||||
{{ if not .username }}
|
|
||||||
send['email'] = send['username'];
|
|
||||||
{{ end }}
|
|
||||||
send = JSON.stringify(send);
|
|
||||||
var req = new XMLHttpRequest();
|
|
||||||
req.open("POST", "/newUser", true);
|
|
||||||
req.responseType = 'json';
|
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
|
||||||
req.onreadystatechange = function() {
|
|
||||||
if (this.readyState == 4) {
|
|
||||||
toggleSpinner();
|
|
||||||
var data = this.response;
|
|
||||||
if ('error' in data || data['success'] == false) {
|
|
||||||
if (typeof(data['error']) != 'undefined') {
|
|
||||||
var errorMessage = data['error'];
|
|
||||||
} else {
|
|
||||||
var errorMessage = 'Unknown Error';
|
|
||||||
}
|
|
||||||
var text = document.createTextNode(errorMessage);
|
|
||||||
var error = document.createElement('button');
|
|
||||||
error.classList.add('btn', 'btn-outline-danger');
|
|
||||||
error.setAttribute('disabled', '');
|
|
||||||
error.appendChild(text);
|
|
||||||
error.id = 'errorMessage';
|
|
||||||
document.getElementById('errorBox').appendChild(error);
|
|
||||||
} else {
|
|
||||||
var valid = true
|
|
||||||
for (var key in data) {
|
|
||||||
if (data.hasOwnProperty(key)) {
|
|
||||||
var criterion = document.getElementById(key);
|
|
||||||
if (criterion) {
|
|
||||||
if (data[key] == false) {
|
|
||||||
valid = false;
|
|
||||||
if (criterion.classList.contains('list-group-item-success')) {
|
|
||||||
criterion.classList.remove('list-group-item-success');
|
|
||||||
criterion.classList.add('list-group-item-danger');
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
if (criterion.classList.contains('list-group-item-danger')) {
|
|
||||||
criterion.classList.remove('list-group-item-danger');
|
|
||||||
criterion.classList.add('list-group-item-success');
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if (valid == true) {
|
|
||||||
successBox.show();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
req.send(send);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
<script src="form.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
2
go.mod
2
go.mod
@ -31,7 +31,7 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14
|
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14
|
||||||
github.com/swaggo/gin-swagger v1.2.0
|
github.com/swaggo/gin-swagger v1.2.0
|
||||||
github.com/swaggo/swag v1.6.8 // indirect
|
github.com/swaggo/swag v1.6.9 // indirect
|
||||||
github.com/ugorji/go v1.1.9 // indirect
|
github.com/ugorji/go v1.1.9 // indirect
|
||||||
github.com/urfave/cli/v2 v2.2.0 // indirect
|
github.com/urfave/cli/v2 v2.2.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -210,6 +210,8 @@ github.com/swaggo/swag v1.6.7 h1:e8GC2xDllJZr3omJkm9YfmK0Y56+rMO3cg0JBKNz09s=
|
|||||||
github.com/swaggo/swag v1.6.7/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc=
|
github.com/swaggo/swag v1.6.7/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc=
|
||||||
github.com/swaggo/swag v1.6.8 h1:z3ZNcpJs/NLMpZcKqXUsBELmmY2Ocy09JXKx5gu3L4M=
|
github.com/swaggo/swag v1.6.8 h1:z3ZNcpJs/NLMpZcKqXUsBELmmY2Ocy09JXKx5gu3L4M=
|
||||||
github.com/swaggo/swag v1.6.8/go.mod h1:a0IpNeMfGidNOcm2TsqODUh9JHdHu3kxDA0UlGbBKjI=
|
github.com/swaggo/swag v1.6.8/go.mod h1:a0IpNeMfGidNOcm2TsqODUh9JHdHu3kxDA0UlGbBKjI=
|
||||||
|
github.com/swaggo/swag v1.6.9 h1:BukKRwZjnEcUxQt7Xgfrt9fpav0hiWw9YimdNO9wssw=
|
||||||
|
github.com/swaggo/swag v1.6.9/go.mod h1:a0IpNeMfGidNOcm2TsqODUh9JHdHu3kxDA0UlGbBKjI=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
|
github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||||
|
18
main.go
18
main.go
@ -67,11 +67,6 @@ type appContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) loadHTML(router *gin.Engine) {
|
func (app *appContext) loadHTML(router *gin.Engine) {
|
||||||
// router.LoadHTMLGlob(filepath.Join(app.local_path, "templates", "*"))
|
|
||||||
// if customHTML := app.config.Section("files").Key("html_templates").MustString(""); customHTML != "" {
|
|
||||||
// app.info.Printf("Loading custom templates from \"%s\"", customHTML)
|
|
||||||
// router.LoadHTMLGlob(filepath.Join(customHTML, "*"))
|
|
||||||
// }
|
|
||||||
customPath := app.config.Section("files").Key("html_templates").MustString("")
|
customPath := app.config.Section("files").Key("html_templates").MustString("")
|
||||||
templatePath := filepath.Join(app.local_path, "templates")
|
templatePath := filepath.Join(app.local_path, "templates")
|
||||||
htmlFiles, err := ioutil.ReadDir(templatePath)
|
htmlFiles, err := ioutil.ReadDir(templatePath)
|
||||||
@ -252,7 +247,8 @@ func start(asDaemon, firstCall bool) {
|
|||||||
var nConfig *os.File
|
var nConfig *os.File
|
||||||
nConfig, err := os.Create(app.config_path)
|
nConfig, err := os.Create(app.config_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.err.Fatalf("Couldn't open config file for writing: \"%s\"", app.config_path)
|
app.err.Printf("Couldn't open config file for writing: \"%s\"", app.config_path)
|
||||||
|
app.err.Fatalf("Error: %s", err)
|
||||||
}
|
}
|
||||||
defer nConfig.Close()
|
defer nConfig.Close()
|
||||||
_, err = io.Copy(nConfig, dConfig)
|
_, err = io.Copy(nConfig, dConfig)
|
||||||
@ -451,11 +447,11 @@ func start(asDaemon, firstCall bool) {
|
|||||||
app.loadStrftime()
|
app.loadStrftime()
|
||||||
|
|
||||||
validatorConf := ValidatorConf{
|
validatorConf := ValidatorConf{
|
||||||
"characters": app.config.Section("password_validation").Key("min_length").MustInt(0),
|
"length": app.config.Section("password_validation").Key("min_length").MustInt(0),
|
||||||
"uppercase characters": app.config.Section("password_validation").Key("upper").MustInt(0),
|
"uppercase": app.config.Section("password_validation").Key("upper").MustInt(0),
|
||||||
"lowercase characters": app.config.Section("password_validation").Key("lower").MustInt(0),
|
"lowercase": app.config.Section("password_validation").Key("lower").MustInt(0),
|
||||||
"numbers": app.config.Section("password_validation").Key("number").MustInt(0),
|
"number": app.config.Section("password_validation").Key("number").MustInt(0),
|
||||||
"special characters": app.config.Section("password_validation").Key("special").MustInt(0),
|
"special": app.config.Section("password_validation").Key("special").MustInt(0),
|
||||||
}
|
}
|
||||||
if !app.config.Section("password_validation").Key("enabled").MustBool(false) {
|
if !app.config.Section("password_validation").Key("enabled").MustBool(false) {
|
||||||
for key := range validatorConf {
|
for key := range validatorConf {
|
||||||
|
38
pwval.go
38
pwval.go
@ -1,8 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,11 +19,11 @@ func (vd *Validator) init(criteria ValidatorConf) {
|
|||||||
|
|
||||||
// This isn't used, its for swagger
|
// This isn't used, its for swagger
|
||||||
type PasswordValidation struct {
|
type PasswordValidation struct {
|
||||||
Characters bool `json:"characters,omitempty"` // Number of characters
|
Characters bool `json:"length,omitempty"` // Number of characters
|
||||||
Lowercase bool `json:"lowercase characters,omitempty"` // Number of lowercase characters
|
Lowercase bool `json:"lowercase,omitempty"` // Number of lowercase characters
|
||||||
Uppercase bool `json:"uppercase characters,omitempty"` // Number of uppercase characters
|
Uppercase bool `json:"uppercase,omitempty"` // Number of uppercase characters
|
||||||
Numbers bool `json:"numbers,omitempty"` // Number of numbers
|
Numbers bool `json:"number,omitempty"` // Number of numbers
|
||||||
Specials bool `json:"special characters,omitempty"` // Number of special characters
|
Specials bool `json:"special,omitempty"` // Number of special characters
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vd *Validator) validate(password string) map[string]bool {
|
func (vd *Validator) validate(password string) map[string]bool {
|
||||||
@ -34,17 +32,17 @@ func (vd *Validator) validate(password string) map[string]bool {
|
|||||||
count[key] = 0
|
count[key] = 0
|
||||||
}
|
}
|
||||||
for _, c := range password {
|
for _, c := range password {
|
||||||
count["characters"] += 1
|
count["length"] += 1
|
||||||
if unicode.IsUpper(c) {
|
if unicode.IsUpper(c) {
|
||||||
count["uppercase characters"] += 1
|
count["uppercase"] += 1
|
||||||
} else if unicode.IsLower(c) {
|
} else if unicode.IsLower(c) {
|
||||||
count["lowercase characters"] += 1
|
count["lowercase"] += 1
|
||||||
} else if unicode.IsNumber(c) {
|
} else if unicode.IsNumber(c) {
|
||||||
count["numbers"] += 1
|
count["numbers"] += 1
|
||||||
} else {
|
} else {
|
||||||
for _, s := range vd.specialChars {
|
for _, s := range vd.specialChars {
|
||||||
if c == s {
|
if c == s {
|
||||||
count["special characters"] += 1
|
count["special"] += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,18 +58,12 @@ func (vd *Validator) validate(password string) map[string]bool {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vd *Validator) getCriteria() map[string]string {
|
func (vd *Validator) getCriteria() ValidatorConf {
|
||||||
lines := map[string]string{}
|
criteria := ValidatorConf{}
|
||||||
for criterion, min := range vd.criteria {
|
for key, num := range vd.criteria {
|
||||||
if min > 0 {
|
if num != 0 {
|
||||||
text := fmt.Sprintf("Must have at least %d ", min)
|
criteria[key] = num
|
||||||
if min == 1 {
|
|
||||||
text += strings.TrimSuffix(criterion, "s")
|
|
||||||
} else {
|
|
||||||
text += criterion
|
|
||||||
}
|
|
||||||
lines[criterion] = text
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lines
|
return criteria
|
||||||
}
|
}
|
||||||
|
39
ts/admin.ts
39
ts/admin.ts
@ -1,45 +1,6 @@
|
|||||||
interface Window {
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set in admin.html
|
// Set in admin.html
|
||||||
var cssFile: string;
|
var cssFile: string;
|
||||||
|
|
||||||
const _get = (url: string, data: Object, onreadystatechange: () => void): void => {
|
|
||||||
let req = new XMLHttpRequest();
|
|
||||||
req.open("GET", url, true);
|
|
||||||
req.responseType = 'json';
|
|
||||||
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
|
||||||
req.onreadystatechange = onreadystatechange;
|
|
||||||
req.send(JSON.stringify(data));
|
|
||||||
};
|
|
||||||
|
|
||||||
const _post = (url: string, data: Object, onreadystatechange: () => void): void => {
|
|
||||||
let req = new XMLHttpRequest();
|
|
||||||
req.open("POST", url, true);
|
|
||||||
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
|
||||||
req.onreadystatechange = onreadystatechange;
|
|
||||||
req.send(JSON.stringify(data));
|
|
||||||
};
|
|
||||||
|
|
||||||
function _delete(url: string, data: Object, onreadystatechange: () => void): void {
|
|
||||||
let req = new XMLHttpRequest();
|
|
||||||
req.open("DELETE", url, true);
|
|
||||||
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
|
||||||
req.onreadystatechange = onreadystatechange;
|
|
||||||
req.send(JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
const rmAttr = (el: HTMLElement, attr: string): void => {
|
|
||||||
if (el.classList.contains(attr)) {
|
|
||||||
el.classList.remove(attr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const addAttr = (el: HTMLElement, attr: string): void => el.classList.add(attr);
|
|
||||||
|
|
||||||
const Focus = (el: HTMLElement): void => rmAttr(el, 'unfocused');
|
const Focus = (el: HTMLElement): void => rmAttr(el, 'unfocused');
|
||||||
const Unfocus = (el: HTMLElement): void => addAttr(el, 'unfocused');
|
const Unfocus = (el: HTMLElement): void => addAttr(el, 'unfocused');
|
||||||
|
|
||||||
|
79
ts/common.ts
Normal file
79
ts/common.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
interface Window {
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeForm(id: string): Object {
|
||||||
|
const form = document.getElementById(id) as HTMLFormElement;
|
||||||
|
let formData = {};
|
||||||
|
for (let i = 0; i < form.elements.length; i++) {
|
||||||
|
const el = form.elements[i];
|
||||||
|
if ((el as HTMLInputElement).type == "submit") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let name = (el as HTMLInputElement).name;
|
||||||
|
if (!name) {
|
||||||
|
name = el.id;
|
||||||
|
}
|
||||||
|
switch ((el as HTMLInputElement).type) {
|
||||||
|
case "checkbox":
|
||||||
|
formData[name] = (el as HTMLInputElement).checked;
|
||||||
|
break;
|
||||||
|
case "text":
|
||||||
|
case "password":
|
||||||
|
case "email":
|
||||||
|
case "number":
|
||||||
|
formData[name] = (el as HTMLInputElement).value;
|
||||||
|
break;
|
||||||
|
case "select-one":
|
||||||
|
case "select":
|
||||||
|
let val: string = (el as HTMLSelectElement).value.toString();
|
||||||
|
if (!isNaN(val as any)) {
|
||||||
|
formData[name] = +val;
|
||||||
|
} else {
|
||||||
|
formData[name] = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rmAttr = (el: HTMLElement, attr: string): void => {
|
||||||
|
if (el.classList.contains(attr)) {
|
||||||
|
el.classList.remove(attr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addAttr = (el: HTMLElement, attr: string): void => el.classList.add(attr);
|
||||||
|
|
||||||
|
const _get = (url: string, data: Object, onreadystatechange: () => void): void => {
|
||||||
|
let req = new XMLHttpRequest();
|
||||||
|
req.open("GET", url, true);
|
||||||
|
req.responseType = 'json';
|
||||||
|
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||||
|
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||||
|
req.onreadystatechange = onreadystatechange;
|
||||||
|
req.send(JSON.stringify(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
const _post = (url: string, data: Object, onreadystatechange: () => void, response?: boolean): void => {
|
||||||
|
let req = new XMLHttpRequest();
|
||||||
|
req.open("POST", url, true);
|
||||||
|
if (response) {
|
||||||
|
req.responseType = 'json';
|
||||||
|
}
|
||||||
|
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||||
|
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||||
|
req.onreadystatechange = onreadystatechange;
|
||||||
|
req.send(JSON.stringify(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
function _delete(url: string, data: Object, onreadystatechange: () => void): void {
|
||||||
|
let req = new XMLHttpRequest();
|
||||||
|
req.open("DELETE", url, true);
|
||||||
|
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||||
|
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||||
|
req.onreadystatechange = onreadystatechange;
|
||||||
|
req.send(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
141
ts/form.ts
Normal file
141
ts/form.ts
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
interface pwValString {
|
||||||
|
singular: string;
|
||||||
|
plural: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface pwValStrings {
|
||||||
|
length, uppercase, lowercase, number, special: pwValString;
|
||||||
|
}
|
||||||
|
|
||||||
|
var validationStrings: pwValStrings;
|
||||||
|
var bsVersion: number;
|
||||||
|
|
||||||
|
var defaultPwValStrings: pwValStrings = {
|
||||||
|
length: {
|
||||||
|
singular: "Must have at least {n} character",
|
||||||
|
plural: "Must have a least {n} characters"
|
||||||
|
},
|
||||||
|
uppercase: {
|
||||||
|
singular: "Must have at least {n} uppercase character",
|
||||||
|
plural: "Must have at least {n} uppercase characters"
|
||||||
|
},
|
||||||
|
lowercase: {
|
||||||
|
singular: "Must have at least {n} lowercase character",
|
||||||
|
plural: "Must have at least {n} lowercase characters"
|
||||||
|
},
|
||||||
|
number: {
|
||||||
|
singular: "Must have at least {n} number",
|
||||||
|
plural: "Must have at least {n} numbers"
|
||||||
|
},
|
||||||
|
special: {
|
||||||
|
singular: "Must have at least {n} special character",
|
||||||
|
plural: "Must have at least {n} special characters"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleSpinner = (): void => {
|
||||||
|
const submitButton = document.getElementById('submitButton') as HTMLButtonElement;
|
||||||
|
if (document.getElementById('createAccountSpinner')) {
|
||||||
|
submitButton.innerHTML = `<span>Create Account</span>`;
|
||||||
|
submitButton.disabled = false;
|
||||||
|
} else {
|
||||||
|
submitButton.innerHTML = `
|
||||||
|
<span id="createAccountSpinner" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>Creating...
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let key in validationStrings) {
|
||||||
|
if (validationStrings[key].singular == "" || !(validationStrings[key].plural.includes("{n}"))) {
|
||||||
|
validationStrings[key].singular = defaultPwValStrings[key].singular;
|
||||||
|
}
|
||||||
|
if (validationStrings[key].plural == "" || !(validationStrings[key].plural.includes("{n}"))) {
|
||||||
|
validationStrings[key].plural = defaultPwValStrings[key].plural;
|
||||||
|
}
|
||||||
|
let el = document.getElementById(key) as HTMLUListElement;
|
||||||
|
if (el) {
|
||||||
|
const min: number = +el.getAttribute("min");
|
||||||
|
let text = "";
|
||||||
|
if (min == 1) {
|
||||||
|
text = validationStrings[key].singular.replace("{n}", "1");
|
||||||
|
} else {
|
||||||
|
text = validationStrings[key].plural.replace("{n}", min.toString());
|
||||||
|
}
|
||||||
|
(document.getElementById(key).children[0] as HTMLDivElement).textContent = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Modal {
|
||||||
|
show: () => void;
|
||||||
|
hide: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
var successBox: Modal;
|
||||||
|
|
||||||
|
if (bsVersion == 5) {
|
||||||
|
var bootstrap: any;
|
||||||
|
successBox = new bootstrap.Modal(document.getElementById('successBox'));
|
||||||
|
} else if (bsVersion == 4) {
|
||||||
|
successBox = {
|
||||||
|
show: (): void => {
|
||||||
|
($('#successBox') as any).modal('show');
|
||||||
|
},
|
||||||
|
hide: (): void => {
|
||||||
|
($('#successBox') as any).modal('hide');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = window.location.href.split('/').pop();
|
||||||
|
var usernameEnabled: boolean;
|
||||||
|
|
||||||
|
(document.getElementById('accountForm') as HTMLFormElement).addEventListener('submit', (event: any): boolean => {
|
||||||
|
event.preventDefault();
|
||||||
|
const el = document.getElementById('errorMessage');
|
||||||
|
if (el) {
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
toggleSpinner();
|
||||||
|
let send: Object = serializeForm('accountForm');
|
||||||
|
send["code"] = code;
|
||||||
|
if (!usernameEnabled) {
|
||||||
|
send["email"] = send["username"];
|
||||||
|
}
|
||||||
|
_post("/newUser", send, function (): void {
|
||||||
|
if (this.readyState == 4) {
|
||||||
|
toggleSpinner();
|
||||||
|
let data: Object = this.response;
|
||||||
|
const errorGiven = ("error" in data)
|
||||||
|
if (errorGiven || data["success"] === false) {
|
||||||
|
let errorMessage = "Unknown Error";
|
||||||
|
if (errorGiven && errorGiven != true) {
|
||||||
|
errorMessage = data["error"];
|
||||||
|
}
|
||||||
|
document.getElementById('errorBox').innerHTML += `
|
||||||
|
<button id="errorMessage" class="btn btn-outline-danger" disabled>${errorMessage}</button>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
let valid = true;
|
||||||
|
for (let key in data) {
|
||||||
|
if (data.hasOwnProperty(key)) {
|
||||||
|
const criterion = document.getElementById(key);
|
||||||
|
if (criterion) {
|
||||||
|
if (data[key] === false) {
|
||||||
|
valid = false;
|
||||||
|
addAttr(criterion, "list-group-item-danger");
|
||||||
|
rmAttr(criterion, "list-group-item-success");
|
||||||
|
} else {
|
||||||
|
addAttr(criterion, "list-group-item-success");
|
||||||
|
rmAttr(criterion, "list-group-item-danger");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid) {
|
||||||
|
successBox.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
return false;
|
||||||
|
});
|
@ -1,35 +0,0 @@
|
|||||||
function serializeForm(id: string): Object {
|
|
||||||
const form = document.getElementById(id) as HTMLFormElement;
|
|
||||||
let formData = {};
|
|
||||||
for (let i = 0; i < form.elements.length; i++) {
|
|
||||||
const el = form.elements[i];
|
|
||||||
if ((el as HTMLInputElement).type == "submit") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let name = (el as HTMLInputElement).name;
|
|
||||||
if (!name) {
|
|
||||||
name = el.id;
|
|
||||||
}
|
|
||||||
switch ((el as HTMLInputElement).type) {
|
|
||||||
case "checkbox":
|
|
||||||
formData[name] = (el as HTMLInputElement).checked;
|
|
||||||
break;
|
|
||||||
case "text":
|
|
||||||
case "password":
|
|
||||||
case "email":
|
|
||||||
case "number":
|
|
||||||
formData[name] = (el as HTMLInputElement).value;
|
|
||||||
break;
|
|
||||||
case "select-one":
|
|
||||||
case "select":
|
|
||||||
let val: string = (el as HTMLSelectElement).value.toString();
|
|
||||||
if (!isNaN(val as any)) {
|
|
||||||
formData[name] = +val;
|
|
||||||
} else {
|
|
||||||
formData[name] = val;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return formData;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user