pull/429/head
Hunter Long 2020-01-19 21:02:15 -08:00
parent 8b4cf43984
commit c4cdc45bc5
12 changed files with 351 additions and 233 deletions

View File

@ -837,45 +837,45 @@
"@fortawesome/fontawesome-common-types@^0.1.2-1":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.1.7.tgz#4336c4b06d0b5608ff1215464b66fcf9f4795284"
resolved "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/0.1.7/fontawesome-common-types-0.1.7.tgz#4336c4b06d0b5608ff1215464b66fcf9f4795284"
integrity sha512-ego8jRVSHfq/iq4KRZJKQeUAdi3ZjGNrqw4oPN3fNdvTBnLCSntwVCnc37bsAJP9UB8MhrTfPnZYxkv2vpS4pg==
"@fortawesome/fontawesome-common-types@^0.2.26":
version "0.2.26"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.26.tgz#6e0b13a752676036f8196f8a1500d53a27b4adc1"
resolved "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/0.2.26/fontawesome-common-types-0.2.26.tgz#6e0b13a752676036f8196f8a1500d53a27b4adc1"
integrity sha512-CcM/fIFwZlRdiWG/25xE/wHbtyUuCtqoCTrr6BsWw7hH072fR++n4L56KPydAr3ANgMJMjT8v83ZFIsDc7kE+A==
"@fortawesome/fontawesome-free-solid@^5.1.0-3":
version "5.1.0-3"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.1.0-3.tgz#60e6e1cc7588b933a570bcfc9eb78b9cadda451a"
resolved "https://npm.fontawesome.com/@fortawesome/fontawesome-free-solid/-/5.1.0-3/fontawesome-free-solid-5.1.0-3.tgz#60e6e1cc7588b933a570bcfc9eb78b9cadda451a"
integrity sha512-E9b+bU91/4538vBvAeaTsvt2r9wTYEoKniuhbq8+RNI08whrUs1RGeaCzyh7ON0rrbJZz/Ae3g8EuCmfsYwfzQ==
dependencies:
"@fortawesome/fontawesome-common-types" "^0.1.2-1"
"@fortawesome/fontawesome-svg-core@^1.2.26":
version "1.2.26"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.26.tgz#671569271d6b532cdea5e3deb8ff16f8b7ac251d"
resolved "https://npm.fontawesome.com/@fortawesome/fontawesome-svg-core/-/1.2.26/fontawesome-svg-core-1.2.26.tgz#671569271d6b532cdea5e3deb8ff16f8b7ac251d"
integrity sha512-3Dfd/v2IztP1TxKOxZiB5+4kaOZK9mNy0KU1vVK7nFlPWz3gzxrCWB+AloQhQUoJ8HhGqbzjliK89Vl7PExGbw==
dependencies:
"@fortawesome/fontawesome-common-types" "^0.2.26"
"@fortawesome/free-brands-svg-icons@^5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.12.0.tgz#b0c78627f811ac030ee0ac88df376567cf74119d"
resolved "https://npm.fontawesome.com/@fortawesome/free-brands-svg-icons/-/5.12.0/free-brands-svg-icons-5.12.0.tgz#b0c78627f811ac030ee0ac88df376567cf74119d"
integrity sha512-50uCFzVUki3wfmFmrMNLFhOt8dP6YZ53zwR4dK9FR7Lwq1IVHXnSBb8MtGLe3urLJ2sA+CSu7Pc7s3i6/zLxmA==
dependencies:
"@fortawesome/fontawesome-common-types" "^0.2.26"
"@fortawesome/free-solid-svg-icons@^5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.12.0.tgz#8decac5844e60453cc0c7c51437d1461df053a35"
resolved "https://npm.fontawesome.com/@fortawesome/free-solid-svg-icons/-/5.12.0/free-solid-svg-icons-5.12.0.tgz#8decac5844e60453cc0c7c51437d1461df053a35"
integrity sha512-CnpsWs6GhTs9ekNB3d8rcO5HYqRkXbYKf2YNiAlTWbj5eVlPqsd/XH1F9If8jkcR1aegryAbln/qYeKVZzpM0g==
dependencies:
"@fortawesome/fontawesome-common-types" "^0.2.26"
"@fortawesome/vue-fontawesome@^0.1.9":
version "0.1.9"
resolved "https://registry.yarnpkg.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-0.1.9.tgz#d3af6d4e50f337327de90447fe35fa1e117a2fbe"
resolved "https://npm.fontawesome.com/@fortawesome/vue-fontawesome/-/0.1.9/vue-fontawesome-0.1.9.tgz#d3af6d4e50f337327de90447fe35fa1e117a2fbe"
integrity sha512-h/emhmZz+DfB2zOGLWawNwXq82UYhn9waTfUjLLmeaIqtnIyNt6kYlpQT/vzJjLZRDRvY2IEJAh1di5qKpKVpA==
"@hapi/address@2.x.x":
@ -1244,11 +1244,11 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1:
version "6.10.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
version "6.11.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9"
integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==
dependencies:
fast-deep-equal "^2.0.1"
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
@ -2605,7 +2605,7 @@ debug@=3.1.0:
dependencies:
ms "2.0.0"
debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5:
debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@ -2648,6 +2648,11 @@ deep-equal@^1.0.1:
object-keys "^1.1.1"
regexp.prototype.flags "^1.2.0"
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@ -2742,6 +2747,11 @@ detect-file@^1.0.0:
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
detect-node@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
@ -2890,9 +2900,9 @@ ejs@^2.6.1:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.322:
version "1.3.336"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.336.tgz#f0e7a3e78f1c9a0385b6693a4a4b7453f0ae6aaf"
integrity sha512-FtazvnXAizSVMxQNPqUcTv2UElY5r3uRPQwiU1Tyg/Yc2UFr+/3wqDoLIV9ES6ablW3IrCcR8uEK2ppxaNPWhw==
version "1.3.338"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.338.tgz#4f33745aed599dfa0fd7b388bf754c164e915168"
integrity sha512-wlmfixuHEc9CkfOKgcqdtzBmRW4NStM9ptl5oPILY2UDyHuSXb3Yit+yLVyLObTgGuMMU36hhnfs2GDJId7ctA==
elliptic@^6.0.0:
version "6.5.2"
@ -2970,9 +2980,9 @@ error-stack-parser@^2.0.0:
stackframe "^1.1.1"
es-abstract@^1.17.0-next.1, es-abstract@^1.17.2:
version "1.17.2"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.2.tgz#965b10af56597b631da15872c17a405e86c1fd46"
integrity sha512-YoKuru3Lyoy7yVTBSH2j7UxTqe/je3dWAruC0sHvZX1GNd5zX8SSLvQqEgO9b3Ex8IW+goFI9arEEsFIbulhOw==
version "1.17.3"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.3.tgz#d921ff5889a3664921094bb13aaf0dfd11818578"
integrity sha512-AwiVPKf3sKGMoWtFw0J7Y4MTZ4Iek67k4COWOwHqS8B9TOZ71DCfcoBmdamy8Y6mj4MDz0+VNUpC2HKHFHA3pg==
dependencies:
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
@ -3378,10 +3388,10 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
fast-deep-equal@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
@ -3644,6 +3654,13 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
fs-minipass@^1.2.5:
version "1.2.7"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
dependencies:
minipass "^2.6.0"
fs-write-stream-atomic@^1.0.8:
version "1.0.10"
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
@ -4108,7 +4125,7 @@ https-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
iconv-lite@0.4.24, iconv-lite@^0.4.24:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -4137,6 +4154,13 @@ iferr@^0.1.5:
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
ignore-walk@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
dependencies:
minimatch "^3.0.4"
ignore@^3.0.11:
version "3.3.10"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
@ -4221,7 +4245,7 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.4:
ini@^1.3.4, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@ -5125,6 +5149,21 @@ minimist@^1.1.3, minimist@^1.2.0:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
dependencies:
safe-buffer "^5.1.2"
yallist "^3.0.0"
minizlib@^1.2.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
dependencies:
minipass "^2.9.0"
mississippi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
@ -5252,6 +5291,15 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
needle@^2.2.1:
version "2.4.0"
resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c"
integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==
dependencies:
debug "^3.2.6"
iconv-lite "^0.4.4"
sax "^1.2.4"
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@ -5335,10 +5383,26 @@ node-libs-browser@^2.0.0, node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
node-pre-gyp@*:
version "0.14.0"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
needle "^2.2.1"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
rc "^1.2.7"
rimraf "^2.6.1"
semver "^5.3.0"
tar "^4.4.2"
node-releases@^1.1.44:
version "1.1.45"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.45.tgz#4cf7e9175d71b1317f15ffd68ce63bce1d53e9f2"
integrity sha512-cXvGSfhITKI8qsV116u2FTzH5EWZJfgG7d4cpqwF8I8+1tWpD6AsvvGRKq2onR0DNj1jfqsjkXZsm14JMS7Cyg==
version "1.1.46"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.46.tgz#6b262afef1bdc9a950a96df2e77e0d2290f484bf"
integrity sha512-YOjdx+Uoh9FbRO7yVYbnbt1puRWPQMemR3SutLeyv2XfxKs1ihpe0OLAUwBPEP2ImNH/PZC7SEiC6j32dwRZ7g==
dependencies:
semver "^6.3.0"
@ -5372,6 +5436,14 @@ node-sass@~4.12:
dependencies:
abbrev "1"
nopt@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
dependencies:
abbrev "1"
osenv "^0.1.4"
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@ -5399,6 +5471,26 @@ normalize-url@^3.0.0:
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
npm-bundled@^1.0.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==
dependencies:
npm-normalize-package-bin "^1.0.1"
npm-normalize-package-bin@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
npm-packlist@^1.1.6:
version "1.4.7"
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848"
integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==
dependencies:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@ -5406,7 +5498,7 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0:
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@ -5629,7 +5721,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
osenv@0:
osenv@0, osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
@ -6424,6 +6516,16 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
rc@^1.2.7:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
dependencies:
deep-extend "^0.6.0"
ini "~1.3.0"
minimist "^1.2.0"
strip-json-comments "~2.0.1"
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@ -6813,7 +6915,7 @@ sass-loader@~7.1:
pify "^3.0.0"
semver "^5.5.0"
sax@~1.2.4:
sax@^1.2.4, sax@~1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
@ -6863,7 +6965,7 @@ selfsigned@^1.9.1:
dependencies:
node-forge "0.9.0"
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@ -7386,7 +7488,7 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
strip-json-comments@^2.0.1:
strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@ -7515,6 +7617,19 @@ tar@^2.0.0:
fstream "^1.0.12"
inherits "2"
tar@^4.4.2:
version "4.4.13"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
dependencies:
chownr "^1.1.1"
fs-minipass "^1.2.5"
minipass "^2.8.6"
minizlib "^1.2.1"
mkdirp "^0.5.0"
safe-buffer "^5.1.2"
yallist "^3.0.3"
terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c"
@ -8322,7 +8437,7 @@ yallist@^2.1.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
yallist@^3.0.2:
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==

View File

@ -34,10 +34,10 @@ type apiResponse struct {
Output interface{} `json:"output,omitempty"`
}
func apiIndexHandler(r *http.Request) (interface{}, error) {
func apiIndexHandler(r *http.Request) interface{} {
coreClone := *core.CoreApp
coreClone.Started = utils.Timezoner(coreClone.Started, coreClone.Timezone)
return *coreClone.ToCore(), nil
return *coreClone.ToCore()
}
func apiRenewHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -43,7 +43,8 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
password := form.Get("password")
user, auth := core.AuthUser(username, password)
if auth {
setJwtToken(user, w)
claim, stt := setJwtToken(user, w)
fmt.Println(claim.Username, stt)
utils.Log.Infoln(fmt.Sprintf("User %v logged in from IP %v", user.Username, r.RemoteAddr))
http.Redirect(w, r, basePath+"dashboard", http.StatusSeeOther)
} else {
@ -123,12 +124,12 @@ func removeJwtToken(w http.ResponseWriter) {
})
}
func setJwtToken(user *core.User, w http.ResponseWriter) (*JwtClaim, string) {
expirationTime := time.Now().Add(24 * time.Hour)
jwtClaim := &JwtClaim{
user.Username,
user.Admin.Bool,
jwt.StandardClaims{
func setJwtToken(user *core.User, w http.ResponseWriter) (JwtClaim, string) {
expirationTime := time.Now().Add(72 * time.Hour)
jwtClaim := JwtClaim{
Username: user.Username,
Admin: user.Admin.Bool,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
}}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaim)

View File

@ -20,6 +20,7 @@ import (
"errors"
"github.com/gorilla/mux"
"github.com/hunterlong/statping/core"
"github.com/hunterlong/statping/types"
"github.com/hunterlong/statping/utils"
"net/http"
)
@ -40,10 +41,18 @@ func groupViewHandler(w http.ResponseWriter, r *http.Request) {
}
// apiAllGroupHandler will show all the groups
func apiAllGroupHandler(r *http.Request) (interface{}, error) {
func apiAllGroupHandler(r *http.Request) interface{} {
auth, admin := IsUser(r), IsAdmin(r)
groups := core.SelectGroups(admin, auth)
return groups, nil
return joinGroups(groups)
}
func joinGroups(groups []*core.Group) []*types.Group {
var g []*types.Group
for _, v := range groups {
g = append(g, v.Group)
}
return g
}
// apiGroupHandler will show a single group

View File

@ -19,13 +19,13 @@ import (
"crypto/subtle"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"github.com/dgrijalva/jwt-go"
"html/template"
"net/http"
"os"
"path"
"reflect"
"strings"
"time"
@ -149,14 +149,14 @@ func IsFullAuthenticated(r *http.Request) bool {
return IsAdmin(r)
}
func getJwtAuth(r *http.Request) (bool, string) {
func getJwtToken(r *http.Request) (JwtClaim, error) {
c, err := r.Cookie(cookieKey)
if err != nil {
utils.Log.Errorln(err)
if err == http.ErrNoCookie {
return false, ""
return JwtClaim{}, err
}
return false, ""
return JwtClaim{}, err
}
tknStr := c.Value
var claims JwtClaim
@ -166,15 +166,26 @@ func getJwtAuth(r *http.Request) (bool, string) {
if err != nil {
utils.Log.Errorln("error getting jwt token: ", err)
if err == jwt.ErrSignatureInvalid {
return false, ""
return JwtClaim{}, err
}
return false, ""
return JwtClaim{}, err
}
if !tkn.Valid {
utils.Log.Errorln("token is not valid")
return false, ""
return claims, errors.New("token is not valid")
}
return claims.Admin, claims.Username
return claims, err
}
func ScopeName(r *http.Request) string {
claim, err := getJwtToken(r)
if err != nil {
return ""
}
if claim.Admin {
return "admin"
}
return "user"
}
// IsAdmin returns true if the user session is an administrator
@ -182,11 +193,15 @@ func IsAdmin(r *http.Request) bool {
if core.SetupMode {
return false
}
admin, username := getJwtAuth(r)
if username == "" {
if os.Getenv("GO_ENV") == "test" {
return true
}
claim, err := getJwtToken(r)
if err != nil {
return false
}
return admin
fmt.Println("user: ", claim.Username, claim.Admin)
return claim.Admin
}
// IsUser returns true if the user is registered
@ -197,9 +212,11 @@ func IsUser(r *http.Request) bool {
if os.Getenv("GO_ENV") == "test" {
return true
}
ff, username := getJwtAuth(r)
fmt.Println(ff, username)
return username != ""
_, err := getJwtToken(r)
if err != nil {
return false
}
return true
}
func loadTemplate(w http.ResponseWriter, r *http.Request) (*template.Template, error) {
@ -290,132 +307,6 @@ func returnJson(d interface{}, w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(d)
}
func safeTypes(obj interface{}) []string {
if reflect.ValueOf(obj).Kind() == reflect.Ptr {
obj = &obj
}
switch v := obj.(type) {
case types.Service:
return types.SafeService
default:
fmt.Printf("%T\n", v)
}
return nil
}
func expandServices(s []types.ServiceInterface) []*types.Service {
var services []*types.Service
for _, v := range s {
services = append(services, v.Select())
}
return services
}
func toSafeJson(input interface{}, onlyAdmin, onlyUsers bool) map[string]interface{} {
thisData := make(map[string]interface{})
t := reflect.TypeOf(input)
elem := reflect.ValueOf(input)
d, _ := json.Marshal(input)
var raw map[string]*json.RawMessage
json.Unmarshal(d, &raw)
if t.Kind() == reflect.Ptr {
input = &input
}
fmt.Println("Type:", t.Name())
fmt.Println("Kind:", t.Kind())
fmt.Println("Fields:", t.NumField())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// Get the field tag value
tag := field.Tag.Get("scope")
tags := strings.Split(tag, ",")
jTags := field.Tag.Get("json")
jsonTag := strings.Split(jTags, ",")
fmt.Println(jsonTag, tag)
if len(jsonTag) == 0 {
continue
}
if jsonTag[0] == "" || jsonTag[0] == "-" {
continue
}
trueValue := elem.Field(i).Interface()
trueValue = fixValue(field, trueValue)
if len(jsonTag) == 2 {
if jsonTag[1] == "omitempty" && trueValue == "" {
continue
}
}
if tag == "" {
thisData[jsonTag[0]] = trueValue
continue
}
if forType(tags, onlyAdmin, onlyUsers) {
thisData[jsonTag[0]] = trueValue
}
fmt.Printf("%d. %v (%v), tags: '%v'\n", i, field.Name, field.Type.Name(), tags)
}
return thisData
}
func returnSafeJson(w http.ResponseWriter, r *http.Request, input interface{}) {
admin, user := IsAdmin(r), IsUser(r)
if reflect.ValueOf(input).Kind() == reflect.Slice {
alldata := make([]map[string]interface{}, 0, 1)
s := reflect.ValueOf(input)
for i := 0; i < s.Len(); i++ {
alldata = append(alldata, toSafeJson(s.Index(i).Interface(), admin, user))
}
returnJson(alldata, w, r)
return
}
returnJson(toSafeJson(input, admin, user), w, r)
}
func fixValue(field reflect.StructField, val interface{}) interface{} {
typeName := field.Type.Name()
switch typeName {
case "NullString":
nullItem := val.(types.NullString)
return nullItem.String
case "NullBool":
nullItem := val.(types.NullBool)
return nullItem.Bool
case "NullFloat64":
nullItem := val.(types.NullFloat64)
return nullItem.Float64
case "NullInt64":
nullItem := val.(types.NullInt64)
return nullItem.Int64
default:
return val
}
}
func forType(tags []string, onlyAdmin, onlyUsers bool) bool {
for _, v := range tags {
if v == "admin" && onlyAdmin {
return true
}
if v == "user" && onlyUsers {
return true
}
}
return false
}
// error404Handler is a HTTP handler for 404 error pages
func error404Handler(w http.ResponseWriter, r *http.Request) {
if usingSSL {

View File

@ -45,13 +45,21 @@ func viewMessageHandler(w http.ResponseWriter, r *http.Request) {
ExecuteResponse(w, r, "message.gohtml", message, nil)
}
func apiAllMessagesHandler(w http.ResponseWriter, r *http.Request) {
func apiAllMessagesHandler(r *http.Request) interface{} {
messages, err := core.SelectMessages()
if err != nil {
sendErrorJson(err, w, r)
return
log.Error(err)
return nil
}
returnJson(messages, w, r)
return joinMessages(messages)
}
func joinMessages(messages []*core.Message) []*types.Message {
var m []*types.Message
for _, v := range messages {
m = append(m, v.Message)
}
return m
}
func apiMessageCreateHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -2,6 +2,7 @@ package handlers
import (
"crypto/subtle"
"encoding/json"
"fmt"
"github.com/hunterlong/statping/core"
"github.com/hunterlong/statping/utils"
@ -15,17 +16,6 @@ var (
authPass string
)
func scopedRoute(handler func(r *http.Request) (interface{}, error)) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := handler(r)
if err != nil {
sendErrorJson(err, w, r)
return
}
returnSafeJson(w, r, data)
})
}
// basicAuthHandler is a middleware to implement HTTP basic authentication using
// AUTH_USERNAME and AUTH_PASSWORD environment variables
func basicAuthHandler(next http.Handler) http.Handler {
@ -60,6 +50,15 @@ func sendLog(next http.Handler) http.Handler {
})
}
func scoped(handler func(r *http.Request) interface{}) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data := handler(r)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(scope{data: data, scope: ScopeName(r)})
})
}
// authenticated is a middleware function to check if user is an Admin before running original request
func authenticated(handler func(w http.ResponseWriter, r *http.Request), redirect bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@ -113,7 +113,7 @@ func Router() *mux.Router {
r.Handle("/group/{id}", http.HandlerFunc(groupViewHandler)).Methods("GET")
// API Routes
r.Handle("/api", scopedRoute(apiIndexHandler))
r.Handle("/api", scoped(apiIndexHandler))
r.Handle("/api/login", http.HandlerFunc(apiLoginHandler)).Methods("POST")
r.Handle("/api/logout", http.HandlerFunc(logoutHandler))
r.Handle("/api/renew", authenticated(apiRenewHandler, false))
@ -124,7 +124,7 @@ func Router() *mux.Router {
r.Handle("/api/integrations/{name}", authenticated(apiIntegrationHandler, false)).Methods("POST")
// API GROUPS Routes
r.Handle("/api/groups", scopedRoute(apiAllGroupHandler)).Methods("GET")
r.Handle("/api/groups", scoped(apiAllGroupHandler)).Methods("GET")
r.Handle("/api/groups", authenticated(apiCreateGroupHandler, false)).Methods("POST")
r.Handle("/api/groups/{id}", readOnly(apiGroupHandler, false)).Methods("GET")
r.Handle("/api/groups/{id}", authenticated(apiGroupUpdateHandler, false)).Methods("POST")
@ -132,9 +132,9 @@ func Router() *mux.Router {
r.Handle("/api/reorder/groups", authenticated(apiGroupReorderHandler, false)).Methods("POST")
// API SERVICE Routes
r.Handle("/api/services", scopedRoute(apiAllServicesHandler)).Methods("GET")
r.Handle("/api/services", scoped(apiAllServicesHandler)).Methods("GET")
r.Handle("/api/services", authenticated(apiCreateServiceHandler, false)).Methods("POST")
r.Handle("/api/services/{id}", scopedRoute(apiServiceHandler)).Methods("GET")
r.Handle("/api/services/{id}", scoped(apiServiceHandler)).Methods("GET")
r.Handle("/api/reorder/services", authenticated(reorderServiceHandler, false)).Methods("POST")
r.Handle("/api/services/{id}/running", authenticated(apiServiceRunningHandler, false)).Methods("POST")
r.Handle("/api/services/{id}/data", cached("30s", "application/json", apiServiceDataHandler)).Methods("GET")
@ -142,9 +142,9 @@ func Router() *mux.Router {
r.Handle("/api/services/{id}/heatmap", cached("30s", "application/json", apiServiceHeatmapHandler)).Methods("GET")
r.Handle("/api/services/{id}", authenticated(apiServiceUpdateHandler, false)).Methods("POST")
r.Handle("/api/services/{id}", authenticated(apiServiceDeleteHandler, false)).Methods("DELETE")
r.Handle("/api/services/{id}/failures", authenticated(apiServiceFailuresHandler, false)).Methods("GET")
r.Handle("/api/services/{id}/failures", scoped(apiServiceFailuresHandler)).Methods("GET")
r.Handle("/api/services/{id}/failures", authenticated(servicesDeleteFailuresHandler, false)).Methods("DELETE")
r.Handle("/api/services/{id}/hits", authenticated(apiServiceHitsHandler, false)).Methods("GET")
r.Handle("/api/services/{id}/hits", scoped(apiServiceHitsHandler)).Methods("GET")
// API INCIDENTS Routes
r.Handle("/api/incidents", readOnly(apiAllIncidentsHandler, false)).Methods("GET")
@ -163,7 +163,7 @@ func Router() *mux.Router {
r.Handle("/api/notifier/{method}/test", authenticated(testNotificationHandler, false)).Methods("POST")
// API MESSAGES Routes
r.Handle("/api/messages", readOnly(apiAllMessagesHandler, false)).Methods("GET")
r.Handle("/api/messages", scoped(apiAllMessagesHandler)).Methods("GET")
r.Handle("/api/messages", authenticated(apiMessageCreateHandler, false)).Methods("POST")
r.Handle("/api/messages/{id}", readOnly(apiMessageGetHandler, false)).Methods("GET")
r.Handle("/api/messages/{id}", authenticated(apiMessageUpdateHandler, false)).Methods("POST")

99
handlers/scope.go Normal file
View File

@ -0,0 +1,99 @@
// Statup
// Copyright (C) 2020. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statup
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package handlers
import (
"encoding/json"
"reflect"
"strings"
)
type scope struct {
data interface{}
scope string
}
// MarshalJSON for Scopr
func (s scope) MarshalJSON() ([]byte, error) {
svc := reflect.ValueOf(s.data)
if svc.Kind() == reflect.Slice {
alldata := make([]map[string]interface{}, 0)
for i := 0; i < svc.Len(); i++ {
objIndex := svc.Index(i)
if objIndex.Kind() == reflect.Ptr {
objIndex = objIndex.Elem()
}
alldata = append(alldata, SafeJson(objIndex.Interface(), s.scope))
}
return json.Marshal(alldata)
}
return json.Marshal(SafeJson(svc.Interface(), s.scope))
}
func SafeJson(input interface{}, scope string) map[string]interface{} {
thisData := make(map[string]interface{})
t := reflect.TypeOf(input)
elem := reflect.ValueOf(input)
d, _ := json.Marshal(input)
var raw map[string]*json.RawMessage
json.Unmarshal(d, &raw)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
tag := field.Tag.Get("scope")
tags := strings.Split(tag, ",")
jTags := field.Tag.Get("json")
jsonTag := strings.Split(jTags, ",")
if len(jsonTag) == 0 {
continue
}
if jsonTag[0] == "" || jsonTag[0] == "-" {
continue
}
trueValue := elem.Field(i).Interface()
if len(jsonTag) == 2 {
if jsonTag[1] == "omitempty" && trueValue == "" {
continue
}
}
if tag == "" {
thisData[jsonTag[0]] = trueValue
continue
}
if forTag(tags, scope) {
thisData[jsonTag[0]] = trueValue
}
}
return thisData
}
func forTag(tags []string, scope string) bool {
for _, v := range tags {
if v == scope {
return true
}
}
return false
}

View File

@ -121,13 +121,13 @@ func servicesViewHandler(w http.ResponseWriter, r *http.Request) {
ExecuteResponse(w, r, "service.gohtml", out, nil)
}
func apiServiceHandler(r *http.Request) (interface{}, error) {
func apiServiceHandler(r *http.Request) interface{} {
vars := mux.Vars(r)
servicer := core.SelectService(utils.ToInt(vars["id"]))
if servicer == nil {
return nil, errors.New("service not found")
return errors.New("service not found")
}
return servicer, nil
return *servicer.Select()
}
func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
@ -292,15 +292,15 @@ func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) {
sendJsonAction(service, "delete", w, r)
}
func apiAllServicesHandler(r *http.Request) (interface{}, error) {
func apiAllServicesHandler(r *http.Request) interface{} {
services := core.Services()
return joinServices(services), nil
return joinServices(services)
}
func joinServices(srvs []types.ServiceInterface) []types.Service {
var services []types.Service
func joinServices(srvs []types.ServiceInterface) []*types.Service {
var services []*types.Service
for _, v := range srvs {
services = append(services, *v.Select())
services = append(services, v.Select())
}
return services
}
@ -316,31 +316,27 @@ func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
sendJsonAction(service, "delete_failures", w, r)
}
func apiServiceFailuresHandler(w http.ResponseWriter, r *http.Request) {
func apiServiceFailuresHandler(r *http.Request) interface{} {
vars := mux.Vars(r)
servicer := core.SelectService(utils.ToInt(vars["id"]))
if servicer == nil {
sendErrorJson(errors.New("service not found"), w, r)
return
return errors.New("service not found")
}
returnJson(servicer.AllFailures(), w, r)
return servicer.AllFailures()
}
func apiServiceHitsHandler(w http.ResponseWriter, r *http.Request) {
func apiServiceHitsHandler(r *http.Request) interface{} {
vars := mux.Vars(r)
servicer := core.SelectService(utils.ToInt(vars["id"]))
if servicer == nil {
sendErrorJson(errors.New("service not found"), w, r)
return
return errors.New("service not found")
}
hits, err := servicer.Hits()
if err != nil {
sendErrorJson(err, w, r)
return
return err
}
returnJson(hits, w, r)
return hits
}
func createServiceHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -27,10 +27,10 @@ type Message struct {
StartOn time.Time `gorm:"column:start_on" json:"start_on"`
EndOn time.Time `gorm:"column:end_on" json:"end_on"`
ServiceId int64 `gorm:"index;column:service" json:"service"`
NotifyUsers NullBool `gorm:"column:notify_users" json:"notify_users"`
NotifyMethod string `gorm:"column:notify_method" json:"notify_method"`
NotifyBefore NullInt64 `gorm:"column:notify_before" json:"notify_before"`
NotifyBeforeScale string `gorm:"column:notify_before_scale" json:"notify_before_scale"`
NotifyUsers NullBool `gorm:"column:notify_users" json:"notify_users" scope:"user,admin"`
NotifyMethod string `gorm:"column:notify_method" json:"notify_method" scope:"user,admin"`
NotifyBefore NullInt64 `gorm:"column:notify_before" json:"notify_before" scope:"user,admin"`
NotifyBeforeScale string `gorm:"column:notify_before_scale" json:"notify_before_scale" scope:"user,admin"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
}

View File

@ -61,7 +61,7 @@ type NullFloat64 struct {
}
// MarshalJSON for NullInt64
func (ni *NullInt64) MarshalJSON() ([]byte, error) {
func (ni NullInt64) MarshalJSON() ([]byte, error) {
if !ni.Valid {
return []byte("null"), nil
}
@ -69,7 +69,7 @@ func (ni *NullInt64) MarshalJSON() ([]byte, error) {
}
// MarshalJSON for NullFloat64
func (ni *NullFloat64) MarshalJSON() ([]byte, error) {
func (ni NullFloat64) MarshalJSON() ([]byte, error) {
if !ni.Valid {
return []byte("null"), nil
}
@ -77,7 +77,7 @@ func (ni *NullFloat64) MarshalJSON() ([]byte, error) {
}
// MarshalJSON for NullBool
func (nb *NullBool) MarshalJSON() ([]byte, error) {
func (nb NullBool) MarshalJSON() ([]byte, error) {
if !nb.Valid {
return []byte("null"), nil
}
@ -85,7 +85,7 @@ func (nb *NullBool) MarshalJSON() ([]byte, error) {
}
// MarshalJSON for NullString
func (ns *NullString) MarshalJSON() ([]byte, error) {
func (ns NullString) MarshalJSON() ([]byte, error) {
if !ns.Valid {
return []byte("null"), nil
}