diff --git a/LICENSE.md b/LICENSE.md
index 2b1a459..56351c0 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,19 +1,7 @@
-Copyright (c) 2017-2019 Netsyms Technologies.
+Copyright (c) 2017-2019 Netsyms Technologies. Some rights reserved.
-If you modify and redistribute this project, you must replace the branding
-assets with your own.
-
-The branding assets include:
- * the application icon
- * the Netsyms N punchcard logo
- * the Netsyms for Business graph logo
-
-If you are unsure if your usage is allowed, please contact us:
-https://netsyms.com/contact
-legal@netsyms.com
-
-All other portions of this application,
-unless otherwise noted (in comments, headers, etc), are licensed as follows:
+Licensed under the Mozilla Public License Version 2.0. Files without MPL header
+comments, including third party code, may be under a different license.
Mozilla Public License Version 2.0
==================================
diff --git a/README.md b/README.md
index bbe2795..bc5e2d3 100644
--- a/README.md
+++ b/README.md
@@ -4,4 +4,4 @@ Camp Portal
An online registration system for the Prickly Pear District Cub Scout Day Camp.
This project is almost definitely not useful to anyone as-is; it was built to
-client specifications.
\ No newline at end of file
+client specifications.
diff --git a/action.php b/action.php
index 90a9687..9df3f07 100644
--- a/action.php
+++ b/action.php
@@ -21,11 +21,11 @@ if ($VARS['action'] !== "signout") {
*/
function returnToSender($msg, $arg = "") {
global $VARS;
- if ($arg == "") {
- header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=" . $msg);
- } else {
- header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=$msg&arg=$arg");
+ $header = "Location: app.php?page=" . urlencode($VARS['source']) . "&msg=$msg";
+ if ($arg != "") {
+ $header .= "&arg=$arg";
}
+ header($header);
die();
}
diff --git a/api/functions.php b/api/functions.php
index 78e84c1..9357a53 100644
--- a/api/functions.php
+++ b/api/functions.php
@@ -48,24 +48,48 @@ function getCensoredKey() {
/**
* Check if the request is allowed
- * @global type $VARS
- * @global type $database
+ * @global array $VARS
* @return bool true if the request should continue, false if the request is bad
*/
function authenticate(): bool {
- global $VARS, $database;
- if (empty($VARS['key'])) {
- return false;
+ global $VARS, $SETTINGS;
+ // HTTP basic auth
+ if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
+ $username = $_SERVER['PHP_AUTH_USER'];
+ $password = $_SERVER['PHP_AUTH_PW'];
+ } else if (!empty($VARS['username']) && !empty($VARS['password'])) {
+ $username = $VARS['username'];
+ $password = $VARS['password'];
} else {
- $key = $VARS['key'];
- if ($database->has('apikeys', ['key' => $key]) !== TRUE) {
- engageRateLimit();
- http_response_code(403);
- Log::insert(LogType::API_BAD_KEY, null, "Key: " . $key);
- return false;
+ return false;
+ }
+ $user = User::byUsername($username);
+ if (!$user->exists()) {
+ return false;
+ }
+ if ($user->checkPassword($password, true)) {
+ // Check that the user has permission to access the app
+ $perms = is_array($SETTINGS['api_permissions']) ? $SETTINGS['api_permissions'] : $SETTINGS['permissions'];
+ foreach ($perms as $perm) {
+ if (!$user->hasPermission($perm)) {
+ return false;
+ }
}
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Get the User whose credentials were used to make the request.
+ */
+function getRequestUser(): User {
+ global $VARS;
+ if (!empty($_SERVER['PHP_AUTH_USER'])) {
+ return User::byUsername($_SERVER['PHP_AUTH_USER']);
+ } else {
+ return User::byUsername($VARS['username']);
}
- return true;
}
function checkVars($vars, $or = false) {
@@ -90,11 +114,13 @@ function checkVars($vars, $or = false) {
continue;
}
}
- $checkmethod = "is_$val";
- if ($checkmethod($VARS[$key]) !== true) {
- $ok[$key] = false;
+
+ if (strpos($val, "/") === 0) {
+ // regex
+ $ok[$key] = preg_match($val, $VARS[$key]) === 1;
} else {
- $ok[$key] = true;
+ $checkmethod = "is_$val";
+ $ok[$key] = !($checkmethod($VARS[$key]) !== true);
}
}
if ($or) {
diff --git a/api/index.php b/api/index.php
index 59d0c2a..23cb28c 100644
--- a/api/index.php
+++ b/api/index.php
@@ -10,6 +10,8 @@ require __DIR__ . '/../required.php';
require __DIR__ . '/functions.php';
require __DIR__ . '/apisettings.php';
+header("Access-Control-Allow-Origin: *");
+
$VARS = $_GET;
if ($_SERVER['REQUEST_METHOD'] != "GET") {
$VARS = array_merge($VARS, $_POST);
@@ -25,13 +27,14 @@ if (json_last_error() == JSON_ERROR_NONE) {
if (strpos($_SERVER['REQUEST_URI'], "/api.php") === FALSE) {
$route = explode("/", substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "api/") + 4));
- if (count($route) > 1) {
+ if (count($route) >= 1) {
$VARS["action"] = $route[0];
}
if (count($route) >= 2 && strpos($route[1], "?") !== 0) {
- $VARS["key"] = $route[1];
-
- for ($i = 2; $i < count($route); $i++) {
+ for ($i = 1; $i < count($route); $i++) {
+ if (empty($route[$i]) || strpos($route[$i], "=") === false) {
+ continue;
+ }
$key = explode("=", $route[$i], 2)[0];
$val = explode("=", $route[$i], 2)[1];
$VARS[$key] = $val;
@@ -49,8 +52,9 @@ if (strpos($_SERVER['REQUEST_URI'], "/api.php") === FALSE) {
}
if (!authenticate()) {
- http_response_code(403);
- die("403 Unauthorized");
+ header('WWW-Authenticate: Basic realm="' . $SETTINGS['site_title'] . '"');
+ header('HTTP/1.1 401 Unauthorized');
+ die("401 Unauthorized: you need to supply valid credentials.");
}
if (empty($VARS['action'])) {
diff --git a/index.php b/index.php
index e4cafd8..1bdd70d 100644
--- a/index.php
+++ b/index.php
@@ -13,8 +13,19 @@ if (!empty($_SESSION['loggedin']) && $_SESSION['loggedin'] === true && !isset($_
die();
}
-if (!empty($_GET['logout'])) {
- // Show a logout message instead of immediately redirecting to login flow
+/**
+ * Show a simple HTML page with a line of text and a button. Matches the UI of
+ * the AccountHub login flow.
+ *
+ * @global type $SETTINGS
+ * @global type $SECURE_NONCE
+ * @global type $Strings
+ * @param string $title Text to show, passed through i18n
+ * @param string $button Button text, passed through i18n
+ * @param string $url URL for the button
+ */
+function showHTML(string $title, string $button, string $url) {
+ global $SETTINGS, $SECURE_NONCE, $Strings;
?>
@@ -26,7 +37,6 @@ if (!empty($_GET['logout'])) {
-
@@ -54,24 +59,25 @@ if (!empty($_GET['logout'])) {
-
get("You have been logged out.") ?>
+ get($title); ?>
-
-
hasPermission($perm)) {
+ showHTML("no access permission", "sign out", "./action.php?action=signout");
+ die();
+ }
+ }
Session::start($user);
$_SESSION["login_code"] = null;
header('Location: app.php');
- die("Logged in, go to app.php");
+ showHTML("Logged in", "Continue", "./app.php");
+ die();
} else {
throw new Exception();
}
@@ -108,7 +121,10 @@ if ($redirecttologin) {
$_SESSION["login_code"] = $codedata["code"];
- header("Location: " . $codedata["loginurl"] . "?code=" . htmlentities($codedata["code"]) . "&redirect=" . htmlentities($redirecturl));
+ $locationurl = $codedata["loginurl"] . "?code=" . htmlentities($codedata["code"]) . "&redirect=" . htmlentities($redirecturl);
+ header("Location: $locationurl");
+ showHTML("Continue", "Continue", $locationurl);
+ die();
} catch (Exception $ex) {
sendError($ex->getMessage());
}
diff --git a/langs/en/core.json b/langs/en/core.json
index 20eac0a..f2d85fb 100644
--- a/langs/en/core.json
+++ b/langs/en/core.json
@@ -1,16 +1,7 @@
{
- "You have been logged out.": "You have been logged out.",
- "Log in again": "Log in again",
- "login server unavailable": "Login server unavailable. Try again later or contact technical support.",
- "welcome user": "Welcome, {user}!",
"sign out": "Sign out",
- "settings": "Settings",
- "options": "Options",
"404 error": "404 Error",
"page not found": "Page not found.",
"invalid parameters": "Invalid request parameters.",
- "login server error": "The login server returned an error: {arg}",
- "login server user data error": "The login server refused to provide account information. Try again or contact technical support.",
- "captcha error": "There was a problem with the CAPTCHA (robot test). Try again.",
- "no access permission": "You do not have permission to access this system."
+ "login server error": "The login server returned an error: {arg}"
}
diff --git a/langs/en/index.json b/langs/en/index.json
new file mode 100644
index 0000000..c516bbb
--- /dev/null
+++ b/langs/en/index.json
@@ -0,0 +1,8 @@
+{
+ "You have been logged out.": "You have been logged out.",
+ "Log in again": "Log in again",
+ "login server unavailable": "Login server unavailable. Try again later or contact technical support.",
+ "no access permission": "You do not have permission to access this system.",
+ "Logged in": "Logged in",
+ "Continue": "Continue"
+}
diff --git a/lib/FormBuilder.lib.php b/lib/FormBuilder.lib.php
index fddbff2..c9d0932 100644
--- a/lib/FormBuilder.lib.php
+++ b/lib/FormBuilder.lib.php
@@ -116,6 +116,41 @@ class FormBuilder {
$this->items[] = $item;
}
+ /**
+ * Add a text input.
+ *
+ * @param string $name Element name
+ * @param string $value Element value
+ * @param bool $required If the element is required for form submission.
+ * @param string $id Element ID
+ * @param string $label Text label to display near the input
+ * @param string $icon FontAwesome icon (example: "fas fa-toilet-paper")
+ * @param int $width Bootstrap column width for the input, out of 12.
+ * @param int $minlength Minimum number of characters for the input.
+ * @param int $maxlength Maximum number of characters for the input.
+ * @param string $pattern Regex pattern for custom client-side validation.
+ * @param string $error Message to show if the input doesn't validate.
+ */
+ public function addTextInput(string $name, string $value = "", bool $required = true, string $id = "", string $label = "", string $icon = "", int $width = 4, int $minlength = 1, int $maxlength = 100, string $pattern = "", string $error = "") {
+ $this->addInput($name, $value, "text", $required, $id, null, $label, $icon, $width, $minlength, $maxlength, $pattern, $error);
+ }
+
+ /**
+ * Add a select dropdown.
+ *
+ * @param string $name Element name
+ * @param string $value Element value
+ * @param bool $required If the element is required for form submission.
+ * @param string $id Element ID
+ * @param array $options Array of [value => text] pairs for a select element
+ * @param string $label Text label to display near the input
+ * @param string $icon FontAwesome icon (example: "fas fa-toilet-paper")
+ * @param int $width Bootstrap column width for the input, out of 12.
+ */
+ public function addSelect(string $name, string $value = "", bool $required = true, string $id = null, array $options = null, string $label = "", string $icon = "", int $width = 4) {
+ $this->addInput($name, $value, "select", $required, $id, $options, $label, $icon, $width);
+ }
+
/**
* Add a button to the form.
*
@@ -173,33 +208,65 @@ HTMLTOP;
$required = $item["required"] ? "required" : "";
$id = empty($item["id"]) ? "" : "id=\"$item[id]\"";
$pattern = empty($item["pattern"]) ? "" : "pattern=\"$item[pattern]\"";
-
+ if (empty($item['type'])) {
+ $item['type'] = "text";
+ }
$itemhtml = "";
+ $itemlabel = "";
+
+ if ($item['type'] == "textarea") {
+ $itemlabel = "";
+ } else if ($item['type'] != "checkbox") {
+ $itemlabel = "";
+ }
+ $strippedlabel = strip_tags($item['label']);
$itemhtml .= <<
ERROR;
}
+ if ($item["type"] != "textarea") {
+ $itemhtml .= "\n ";
+ }
$itemhtml .= <<
-
+\n
\n
ITEMBOTTOM;
$html .= $itemhtml;
@@ -224,7 +293,7 @@ ITEMBOTTOM;
HTMLBOTTOM;
if (!empty($this->buttons)) {
- $html .= "\n ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:vn},Ln="show",xn="out",Pn={HIDE:"hide"+Tn,HIDDEN:"hidden"+Tn,SHOW:"show"+Tn,SHOWN:"shown"+Tn,INSERTED:"inserted"+Tn,CLICK:"click"+Tn,FOCUSIN:"focusin"+Tn,FOCUSOUT:"focusout"+Tn,MOUSEENTER:"mouseenter"+Tn,MOUSELEAVE:"mouseleave"+Tn},Hn="fade",jn="show",Rn=".tooltip-inner",Fn=".arrow",Mn="hover",Wn="focus",Un="click",Bn="manual",qn=function(){function i(t,e){if("undefined"==typeof be)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=p(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),p(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(p(this.getTipElement()).hasClass(jn))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),p.removeData(this.element,this.constructor.DATA_KEY),p(this.element).off(this.constructor.EVENT_KEY),p(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&p(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===p(this.element).css("display"))throw new Error("Please use show on visible elements");var t=p.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){p(this.element).trigger(t);var n=m.findShadowRoot(this.element),i=p.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=m.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&p(o).addClass(Hn);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();p(o).data(this.constructor.DATA_KEY,this),p.contains(this.element.ownerDocument.documentElement,this.tip)||p(o).appendTo(l),p(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new be(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:Fn},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),p(o).addClass(jn),"ontouchstart"in document.documentElement&&p(document.body).children().on("mouseover",null,p.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,p(e.element).trigger(e.constructor.Event.SHOWN),t===xn&&e._leave(null,e)};if(p(this.tip).hasClass(Hn)){var h=m.getTransitionDurationFromElement(this.tip);p(this.tip).one(m.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=p.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==Ln&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),p(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(p(this.element).trigger(i),!i.isDefaultPrevented()){if(p(n).removeClass(jn),"ontouchstart"in document.documentElement&&p(document.body).children().off("mouseover",null,p.noop),this._activeTrigger[Un]=!1,this._activeTrigger[Wn]=!1,this._activeTrigger[Mn]=!1,p(this.tip).hasClass(Hn)){var r=m.getTransitionDurationFromElement(n);p(n).one(m.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){p(this.getTipElement()).addClass(Dn+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||p(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(p(t.querySelectorAll(Rn)),this.getTitle()),p(t).removeClass(Hn+" "+jn)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=bn(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?p(e).parent().is(t)||t.empty().append(e):t.text(p(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:m.isElement(this.config.container)?p(this.config.container):p(document).find(this.config.container)},t._getAttachment=function(t){return Nn[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)p(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Bn){var e=t===Mn?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===Mn?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;p(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),p(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||p(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Wn:Mn]=!0),p(e.getTipElement()).hasClass(jn)||e._hoverState===Ln?e._hoverState=Ln:(clearTimeout(e._timeout),e._hoverState=Ln,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===Ln&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||p(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Wn:Mn]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=xn,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===xn&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=p(this.element).data();return Object.keys(e).forEach(function(t){-1!==An.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),m.typeCheckConfig(wn,t,this.constructor.DefaultType),t.sanitize&&(t.template=bn(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=p(this.getTipElement()),e=t.attr("class").match(In);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(p(t).removeClass(Hn),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=p(this).data(Cn),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),p(this).data(Cn,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return kn}},{key:"NAME",get:function(){return wn}},{key:"DATA_KEY",get:function(){return Cn}},{key:"Event",get:function(){return Pn}},{key:"EVENT_KEY",get:function(){return Tn}},{key:"DefaultType",get:function(){return On}}]),i}();p.fn[wn]=qn._jQueryInterface,p.fn[wn].Constructor=qn,p.fn[wn].noConflict=function(){return p.fn[wn]=Sn,qn._jQueryInterface};var Kn="popover",Qn="bs.popover",Vn="."+Qn,Yn=p.fn[Kn],zn="bs-popover",Xn=new RegExp("(^|\\s)"+zn+"\\S+","g"),Gn=l({},qn.Default,{placement:"right",trigger:"click",content:"",template:''}),$n=l({},qn.DefaultType,{content:"(string|element|function)"}),Jn="fade",Zn="show",ti=".popover-header",ei=".popover-body",ni={HIDE:"hide"+Vn,HIDDEN:"hidden"+Vn,SHOW:"show"+Vn,SHOWN:"shown"+Vn,INSERTED:"inserted"+Vn,CLICK:"click"+Vn,FOCUSIN:"focusin"+Vn,FOCUSOUT:"focusout"+Vn,MOUSEENTER:"mouseenter"+Vn,MOUSELEAVE:"mouseleave"+Vn},ii=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){p(this.getTipElement()).addClass(zn+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||p(this.config.template)[0],this.tip},o.setContent=function(){var t=p(this.getTipElement());this.setElementContent(t.find(ti),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(ei),e),t.removeClass(Jn+" "+Zn)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=p(this.getTipElement()),e=t.attr("class").match(Xn);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active",Ri='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',Fi=".dropdown-toggle",Mi="> .dropdown-menu .active",Wi=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&p(this._element).hasClass(Oi)||p(this._element).hasClass(Ni))){var t,i,e=p(this._element).closest(Pi)[0],o=m.getSelectorFromElement(this._element);if(e){var r="UL"===e.nodeName||"OL"===e.nodeName?ji:Hi;i=(i=p.makeArray(p(e).find(r)))[i.length-1]}var s=p.Event(Ii.HIDE,{relatedTarget:this._element}),a=p.Event(Ii.SHOW,{relatedTarget:i});if(i&&p(i).trigger(s),p(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(t=document.querySelector(o)),this._activate(this._element,e);var l=function(){var t=p.Event(Ii.HIDDEN,{relatedTarget:n._element}),e=p.Event(Ii.SHOWN,{relatedTarget:i});p(i).trigger(t),p(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){p.removeData(this._element,Ti),this._element=null},t._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?p(e).children(Hi):p(e).find(ji))[0],r=n&&o&&p(o).hasClass(ki),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=m.getTransitionDurationFromElement(o);p(o).removeClass(Li).one(m.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},t._transitionComplete=function(t,e,n){if(e){p(e).removeClass(Oi);var i=p(e.parentNode).find(Mi)[0];i&&p(i).removeClass(Oi),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(p(t).addClass(Oi),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),m.reflow(t),t.classList.contains(ki)&&t.classList.add(Li),t.parentNode&&p(t.parentNode).hasClass(Ai)){var o=p(t).closest(xi)[0];if(o){var r=[].slice.call(o.querySelectorAll(Fi));p(r).addClass(Oi)}t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=p(this),e=t.data(Ti);if(e||(e=new i(this),t.data(Ti,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();p(document).on(Ii.CLICK_DATA_API,Ri,function(t){t.preventDefault(),Wi._jQueryInterface.call(p(this),"show")}),p.fn.tab=Wi._jQueryInterface,p.fn.tab.Constructor=Wi,p.fn.tab.noConflict=function(){return p.fn.tab=Di,Wi._jQueryInterface};var Ui="toast",Bi="bs.toast",qi="."+Bi,Ki=p.fn[Ui],Qi={CLICK_DISMISS:"click.dismiss"+qi,HIDE:"hide"+qi,HIDDEN:"hidden"+qi,SHOW:"show"+qi,SHOWN:"shown"+qi},Vi="fade",Yi="hide",zi="show",Xi="showing",Gi={animation:"boolean",autohide:"boolean",delay:"number"},$i={animation:!0,autohide:!0,delay:500},Ji='[data-dismiss="toast"]',Zi=function(){function i(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var t=i.prototype;return t.show=function(){var t=this;p(this._element).trigger(Qi.SHOW),this._config.animation&&this._element.classList.add(Vi);var e=function(){t._element.classList.remove(Xi),t._element.classList.add(zi),p(t._element).trigger(Qi.SHOWN),t._config.autohide&&t.hide()};if(this._element.classList.remove(Yi),this._element.classList.add(Xi),this._config.animation){var n=m.getTransitionDurationFromElement(this._element);p(this._element).one(m.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},t.hide=function(t){var e=this;this._element.classList.contains(zi)&&(p(this._element).trigger(Qi.HIDE),t?this._close():this._timeout=setTimeout(function(){e._close()},this._config.delay))},t.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(zi)&&this._element.classList.remove(zi),p(this._element).off(Qi.CLICK_DISMISS),p.removeData(this._element,Bi),this._element=null,this._config=null},t._getConfig=function(t){return t=l({},$i,p(this._element).data(),"object"==typeof t&&t?t:{}),m.typeCheckConfig(Ui,t,this.constructor.DefaultType),t},t._setListeners=function(){var t=this;p(this._element).on(Qi.CLICK_DISMISS,Ji,function(){return t.hide(!0)})},t._close=function(){var t=this,e=function(){t._element.classList.add(Yi),p(t._element).trigger(Qi.HIDDEN)};if(this._element.classList.remove(zi),this._config.animation){var n=m.getTransitionDurationFromElement(this._element);p(this._element).one(m.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},i._jQueryInterface=function(n){return this.each(function(){var t=p(this),e=t.data(Bi);if(e||(e=new i(this,"object"==typeof n&&n),t.data(Bi,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"DefaultType",get:function(){return Gi}},{key:"Default",get:function(){return $i}}]),i}();p.fn[Ui]=Zi._jQueryInterface,p.fn[Ui].Constructor=Zi,p.fn[Ui].noConflict=function(){return p.fn[Ui]=Ki,Zi._jQueryInterface},function(){if("undefined"==typeof p)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=p.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||4<=t[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),t.Util=m,t.Alert=g,t.Button=k,t.Carousel=at,t.Collapse=Ct,t.Dropdown=Xe,t.Modal=gn,t.Popover=ii,t.Scrollspy=Ci,t.Tab=Wi,t.Toast=Zi,t.Tooltip=qn,Object.defineProperty(t,"__esModule",{value:!0})});
//# sourceMappingURL=bootstrap.bundle.min.js.map
\ No newline at end of file
diff --git a/static/js/editpayment.js b/static/js/editpayment.js
index abfa584..e397bf8 100644
--- a/static/js/editpayment.js
+++ b/static/js/editpayment.js
@@ -12,5 +12,5 @@ $("#savebutton").click(function (event) {
event.preventDefault()
event.stopPropagation()
}
- form.addClass('was-validated');
+ form.addClass("was-validated");
});
\ No newline at end of file
diff --git a/static/js/fontawesome-all.min.js b/static/js/fontawesome-all.min.js
index 498e4a0..323f3b7 100644
--- a/static/js/fontawesome-all.min.js
+++ b/static/js/fontawesome-all.min.js
@@ -1,5 +1 @@
-/*!
- * Font Awesome Free 5.6.0 by @fontawesome - https://fontawesome.com
- * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
- */
-!function(){"use strict";var c={},l={};try{"undefined"!=typeof window&&(c=window),"undefined"!=typeof document&&(l=document)}catch(c){}var h=(c.navigator||{}).userAgent,z=void 0===h?"":h,v=c,m=l,s=(v.document,!!m.documentElement&&!!m.head&&"function"==typeof m.addEventListener&&m.createElement,~z.indexOf("MSIE")||z.indexOf("Trident/"),"___FONT_AWESOME___"),e=function(){try{return!0}catch(c){return!1}}();var a=v||{};a[s]||(a[s]={}),a[s].styles||(a[s].styles={}),a[s].hooks||(a[s].hooks={}),a[s].shims||(a[s].shims=[]);var M=a[s];function t(c,z){var l=Object.keys(z).reduce(function(c,l){var h=z[l];return!!h.icon?c[h.iconName]=h.icon:c[l]=h,c},{});"function"==typeof M.hooks.addPack?M.hooks.addPack(c,l):M.styles[c]=function(v){for(var c=1;c>>0;h--;)l[h]=c[h];return l}function W(c){return c.classList?D(c.classList):(c.getAttribute("class")||"").split(" ").filter(function(c){return c})}function Y(c,l){var h,z=l.split("-"),v=z[0],m=z.slice(1).join("-");return v!==c||""===m||(h=m,~x.indexOf(h))?null:m}function G(c){return"".concat(c).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}function J(h){return Object.keys(h||{}).reduce(function(c,l){return c+"".concat(l,": ").concat(h[l],";")},"")}function Q(c){return c.size!==R.size||c.x!==R.x||c.y!==R.y||c.rotate!==R.rotate||c.flipX||c.flipY}function Z(c){var l=c.transform,h=c.containerWidth,z=c.iconWidth,v={transform:"translate(".concat(h/2," 256)")},m="translate(".concat(32*l.x,", ").concat(32*l.y,") "),s="scale(".concat(l.size/16*(l.flipX?-1:1),", ").concat(l.size/16*(l.flipY?-1:1),") "),e="rotate(".concat(l.rotate," 0 0)");return{outer:v,inner:{transform:"".concat(m," ").concat(s," ").concat(e)},path:{transform:"translate(".concat(z/2*-1," -256)")}}}var $={x:0,y:0,width:"100%",height:"100%"};function cc(c){var l=c.icons,h=l.main,z=l.mask,v=c.prefix,m=c.iconName,s=c.transform,e=c.symbol,a=c.title,M=c.extra,t=c.watchable,f=void 0!==t&&t,r=z.found?z:h,H=r.width,n=r.height,V="fa-w-".concat(Math.ceil(H/n*16)),i=[U.replacementClass,m?"".concat(U.familyPrefix,"-").concat(m):"",V].filter(function(c){return-1===M.classes.indexOf(c)}).concat(M.classes).join(" "),o={children:[],attributes:B({},M.attributes,{"data-prefix":v,"data-icon":m,class:i,role:"img",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 ".concat(H," ").concat(n)})};f&&(o.attributes[X]=""),a&&o.children.push({tag:"title",attributes:{id:o.attributes["aria-labelledby"]||"title-".concat(K())},children:[a]});var C,L,d,u,p,b,g,S,y,w,k,A,x,q,O,j,E,N,P,T,_,R,F,I=B({},o,{prefix:v,iconName:m,main:h,mask:z,transform:s,symbol:e,styles:M.styles}),D=z.found&&h.found?(L=(C=I).children,d=C.attributes,u=C.main,p=C.mask,b=C.transform,g=u.width,S=u.icon,y=p.width,w=p.icon,k=Z({transform:b,containerWidth:y,iconWidth:g}),A={tag:"rect",attributes:B({},$,{fill:"white"})},x={tag:"g",attributes:B({},k.inner),children:[{tag:"path",attributes:B({},S.attributes,k.path,{fill:"black"})}]},q={tag:"g",attributes:B({},k.outer),children:[x]},O="mask-".concat(K()),j="clip-".concat(K()),E={tag:"defs",children:[{tag:"clipPath",attributes:{id:j},children:[w]},{tag:"mask",attributes:B({},$,{id:O,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[A,q]}]},L.push(E,{tag:"rect",attributes:B({fill:"currentColor","clip-path":"url(#".concat(j,")"),mask:"url(#".concat(O,")")},$)}),{children:L,attributes:d}):function(c){var l=c.children,h=c.attributes,z=c.main,v=c.transform,m=J(c.styles);if(0").concat(s.map(Lc).join(""),"").concat(l,">")}var dc=function(){};function uc(c){return"string"==typeof(c.getAttribute?c.getAttribute(X):null)}var pc={replace:function(c){var l=c[0],h=c[1].map(function(c){return Lc(c)}).join("\n");if(l.parentNode&&l.outerHTML)l.outerHTML=h+(U.keepOriginalSource&&"svg"!==l.tagName.toLowerCase()?"\x3c!-- ".concat(l.outerHTML," --\x3e"):"");else if(l.parentNode){var z=document.createElement("span");l.parentNode.replaceChild(z,l),z.outerHTML=h}},nest:function(c){var l=c[0],h=c[1];if(~W(l).indexOf(U.replacementClass))return pc.replace(c);var z=new RegExp("".concat(U.familyPrefix,"-.*"));delete h[0].attributes.style;var v=h[0].attributes.class.split(" ").reduce(function(c,l){return l===U.replacementClass||l.match(z)?c.toSvg.push(l):c.toNode.push(l),c},{toNode:[],toSvg:[]});h[0].attributes.class=v.toSvg.join(" ");var m=h.map(function(c){return Lc(c)}).join("\n");l.setAttribute("class",v.toNode.join(" ")),l.setAttribute(X,""),l.innerHTML=m}};function bc(h,c){var z="function"==typeof c?c:dc;0===h.length?z():(H.requestAnimationFrame||function(c){return c()})(function(){var c=!0===U.autoReplaceSvg?pc.replace:pc[U.autoReplaceSvg]||pc.replace,l=sc.begin("mutate");h.map(c),l(),z()})}var gc=!1;var Sc=null;function yc(c){if(M&&U.observeMutations){var v=c.treeCallback,m=c.nodeCallback,s=c.pseudoElementsCallback,l=c.observeMutationsRoot,h=void 0===l?n.body:l;Sc=new M(function(c){gc||D(c).forEach(function(c){if("childList"===c.type&&0>>0;h--;)l[h]=c[h];return l}function pc(c){return c.classList?dc(c.classList):(c.getAttribute("class")||"").split(" ").filter(function(c){return c})}function bc(c,l){var h,z=l.split("-"),v=z[0],m=z.slice(1).join("-");return v!==c||""===m||(h=m,~_.indexOf(h))?null:m}function gc(c){return"".concat(c).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}function Sc(h){return Object.keys(h||{}).reduce(function(c,l){return c+"".concat(l,": ").concat(h[l],";")},"")}function yc(c){return c.size!==Vc.size||c.x!==Vc.x||c.y!==Vc.y||c.rotate!==Vc.rotate||c.flipX||c.flipY}function wc(c){var l=c.transform,h=c.containerWidth,z=c.iconWidth,v={transform:"translate(".concat(h/2," 256)")},m="translate(".concat(32*l.x,", ").concat(32*l.y,") "),s="scale(".concat(l.size/16*(l.flipX?-1:1),", ").concat(l.size/16*(l.flipY?-1:1),") "),e="rotate(".concat(l.rotate," 0 0)");return{outer:v,inner:{transform:"".concat(m," ").concat(s," ").concat(e)},path:{transform:"translate(".concat(z/2*-1," -256)")}}}var kc={x:0,y:0,width:"100%",height:"100%"};function Ac(c){var l=c.icons,h=l.main,z=l.mask,v=c.prefix,m=c.iconName,s=c.transform,e=c.symbol,a=c.title,t=c.extra,M=c.watchable,f=void 0!==M&&M,r=z.found?z:h,n=r.width,H=r.height,i="fa-w-".concat(Math.ceil(n/H*16)),o=[U.replacementClass,m?"".concat(U.familyPrefix,"-").concat(m):"",i].filter(function(c){return-1===t.classes.indexOf(c)}).concat(t.classes).join(" "),V={children:[],attributes:X({},t.attributes,{"data-prefix":v,"data-icon":m,class:o,role:"img",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 ".concat(n," ").concat(H)})};f&&(V.attributes[B]=""),a&&V.children.push({tag:"title",attributes:{id:V.attributes["aria-labelledby"]||"title-".concat(uc())},children:[a]});var C,L,u,d,p,b,g,S,y,w,k,A,x,j,q,O,E,P,N,_,T,R,F,I=X({},V,{prefix:v,iconName:m,main:h,mask:z,transform:s,symbol:e,styles:t.styles}),D=z.found&&h.found?(L=(C=I).children,u=C.attributes,d=C.main,p=C.mask,b=C.transform,g=d.width,S=d.icon,y=p.width,w=p.icon,k=wc({transform:b,containerWidth:y,iconWidth:g}),A={tag:"rect",attributes:X({},kc,{fill:"white"})},x={tag:"g",attributes:X({},k.inner),children:[{tag:"path",attributes:X({},S.attributes,k.path,{fill:"black"})}]},j={tag:"g",attributes:X({},k.outer),children:[x]},q="mask-".concat(uc()),O="clip-".concat(uc()),E={tag:"defs",children:[{tag:"clipPath",attributes:{id:O},children:[w]},{tag:"mask",attributes:X({},kc,{id:q,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[A,j]}]},L.push(E,{tag:"rect",attributes:X({fill:"currentColor","clip-path":"url(#".concat(O,")"),mask:"url(#".concat(q,")")},kc)}),{children:L,attributes:u}):function(c){var l=c.children,h=c.attributes,z=c.main,v=c.transform,m=Sc(c.styles);if(0").concat(s.map(Kc).join(""),"").concat(l,">")}var Gc=function(){};function Jc(c){return"string"==typeof(c.getAttribute?c.getAttribute(B):null)}var Qc={replace:function(c){var l=c[0],h=c[1].map(function(c){return Kc(c)}).join("\n");if(l.parentNode&&l.outerHTML)l.outerHTML=h+(U.keepOriginalSource&&"svg"!==l.tagName.toLowerCase()?"\x3c!-- ".concat(l.outerHTML," --\x3e"):"");else if(l.parentNode){var z=document.createElement("span");l.parentNode.replaceChild(z,l),z.outerHTML=h}},nest:function(c){var l=c[0],h=c[1];if(~pc(l).indexOf(U.replacementClass))return Qc.replace(c);var z=new RegExp("".concat(U.familyPrefix,"-.*"));delete h[0].attributes.style;var v=h[0].attributes.class.split(" ").reduce(function(c,l){return l===U.replacementClass||l.match(z)?c.toSvg.push(l):c.toNode.push(l),c},{toNode:[],toSvg:[]});h[0].attributes.class=v.toSvg.join(" ");var m=h.map(function(c){return Kc(c)}).join("\n");l.setAttribute("class",v.toNode.join(" ")),l.setAttribute(B,""),l.innerHTML=m}};function Zc(h,c){var z="function"==typeof c?c:Gc;0===h.length?z():(H.requestAnimationFrame||function(c){return c()})(function(){var c=!0===U.autoReplaceSvg?Qc.replace:Qc[U.autoReplaceSvg]||Qc.replace,l=Pc.begin("mutate");h.map(c),l(),z()})}var $c=!1;function cl(){$c=!1}var ll=null;function hl(c){if(t&&U.observeMutations){var v=c.treeCallback,m=c.nodeCallback,s=c.pseudoElementsCallback,l=c.observeMutationsRoot,h=void 0===l?i:l;ll=new t(function(c){$c||dc(c).forEach(function(c){if("childList"===c.type&&0