Merge master to dev... because I'm an idiot

This commit is contained in:
Matthew Ross 2020-09-05 14:05:59 -04:00
commit 99d55dcddb
20 changed files with 3336 additions and 2902 deletions

View File

@ -1,3 +1,22 @@
## v1.0.2
### New Features
* German translation - Thanks to @ben-so
### Updates
* N/A
### Bug Fixes
* New user creation defaults Security Level to User
* Drag-and-drop automatic actions correctly update UI
* Special characters in emails now handled correctly - Contributed by @ben-so
* Changing card order now updates UI correctly
* Token refresh no longer causes user to be logged out
* Minor fixes for Spanish translations
## v1.0.1
### New Features

View File

@ -195,11 +195,11 @@ Because I like seeing the numbers.
Language | Files | Blank | Comment | Code
-----------|--------:|---------:|---------:|---------:
TypeScript | 69 | 1032 | 122 | 4307
PHP | 21 | 790 | 40 | 2396
HTML | 22 | 287 | 2 | 1604
SASS | 14 | 302 | 10 | 1365
**SUM:** | **126** | **2411** | **174** | **9672**
TypeScript | 67 | 977 | 129 | 4103
PHP | 20 | 744 | 37 | 2243
HTML | 21 | 268 | 2 | 1572
SASS | 14 | 299 | 10 | 1347
**SUM:** | **122** | **2288** | **178** | **9265**
Command: `cloc --exclude-dir=vendor,favicons --exclude-ext=json,svg,ini src/`
@ -207,8 +207,8 @@ Command: `cloc --exclude-dir=vendor,favicons --exclude-ext=json,svg,ini src/`
Language | Files | Blank | Comment | Code
-----------|-------:|---------:|---------:|---------:
TypeScript | 38 | 1018 | 8 | 3544
PHP | 11 | 795 | 19 | 2301
**SUM:** | **49** | **1813** | **27** | **5845**
TypeScript | 38 | 1017 | 8 | 3540
PHP | 11 | 784 | 19 | 2272
**SUM:** | **49** | **1801** | **27** | **5812**
Command: `cloc --exclude-ext=xml test/`

5716
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -51,57 +51,56 @@
}
},
"dependencies": {
"@angular/animations": "^9.1.11",
"@angular/cdk": "^9.2.4",
"@angular/common": "^9.1.11",
"@angular/compiler": "^9.1.11",
"@angular/core": "^9.1.11",
"@angular/forms": "^9.1.11",
"@angular/platform-browser": "^9.1.11",
"@angular/platform-browser-dynamic": "^9.1.11",
"@angular/router": "^9.1.11",
"ajv": "^6.12.2",
"@angular/animations": "^10.0.11",
"@angular/cdk": "^10.1.3",
"@angular/common": "^10.0.11",
"@angular/compiler": "^10.0.11",
"@angular/core": "^10.0.11",
"@angular/forms": "^10.0.11",
"@angular/platform-browser": "^10.0.11",
"@angular/platform-browser-dynamic": "^10.0.11",
"@angular/router": "^10.0.11",
"ajv": "^6.12.4",
"chartist": "^0.11.4",
"chartist-plugin-tooltips": "^0.0.17",
"classlist.js": "^1.1.20150312",
"core-js": "^3.6.5",
"highlight.js": "^10.1.1",
"marked": "^1.1.0",
"highlight.js": "^10.1.2",
"marked": "^1.1.1",
"node-sass": "^4.14.1",
"rxjs": "^6.5.5",
"rxjs": "^6.6.2",
"scss-base": "^1.4.0",
"zone.js": "^0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.901.9",
"@angular/cli": "^9.1.9",
"@angular/compiler-cli": "^9.1.11",
"@angular/language-service": "^9.1.11",
"@types/chartist": "^0.9.48",
"@angular-devkit/build-angular": "^0.1000.6",
"@angular/cli": "^10.0.6",
"@angular/compiler-cli": "^10.0.11",
"@angular/language-service": "^10.0.11",
"@types/chartist": "^0.11.0",
"@types/highlight.js": "^9.12.4",
"@types/jasmine": "~3.5.10",
"@types/jasmine": "~3.5.12",
"@types/jasminewd2": "~2.0.8",
"@types/marked": "^0.7.4",
"@types/node": "^14.0.13",
"@types/marked": "^1.1.0",
"@types/node": "^14.6.0",
"bourbon": "7.0.0",
"bourbon-neat": "4.0.0",
"codelyzer": "^5.2.2",
"codelyzer": "^6.0.0",
"husky": "^4.2.5",
"jasmine": "^3.5.0",
"jasmine-core": "^3.5.0",
"jasmine": "^3.6.1",
"jasmine-core": "^3.6.0",
"jasmine-spec-reporter": "~5.0.2",
"karma": "^5.1.0",
"karma": "^5.1.1",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^3.3.1",
"karma-jasmine": "^4.0.1",
"karma-jasmine-html-reporter": "^1.5.4",
"npm-run-all": "^4.1.5",
"npm-watch": "^0.6.0",
"npm-watch": "^0.7.0",
"protractor": "^7.0.0",
"puppeteer": "^4.0.0",
"puppeteer": "^5.2.1",
"ts-node": "^8.10.2",
"tslib": "^1.13.0",
"tslint": "^6.1.2",
"typescript": "~3.8.3"
"tslint": "^6.1.3",
"typescript": "^3.9.7"
}
}

221
src/api/composer.lock generated
View File

@ -221,16 +221,16 @@
},
{
"name": "monolog/monolog",
"version": "2.1.0",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "38914429aac460e8e4616c8cb486ecb40ec90bb1"
"reference": "f9eee5cec93dfb313a38b6b288741e84e53f02d5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/38914429aac460e8e4616c8cb486ecb40ec90bb1",
"reference": "38914429aac460e8e4616c8cb486ecb40ec90bb1",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f9eee5cec93dfb313a38b6b288741e84e53f02d5",
"reference": "f9eee5cec93dfb313a38b6b288741e84e53f02d5",
"shasum": ""
},
"require": {
@ -308,24 +308,24 @@
"type": "tidelift"
}
],
"time": "2020-05-22T08:12:19+00:00"
"time": "2020-07-23T08:41:23+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.9.5",
"version": "1.10.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "b2c28789e80a97badd14145fda39b545d83ca3ef"
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef",
"reference": "b2c28789e80a97badd14145fda39b545d83ca3ef",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
"shasum": ""
},
"require": {
"php": "^7.1"
"php": "^7.1 || ^8.0"
},
"replace": {
"myclabs/deep-copy": "self.version"
@ -356,7 +356,13 @@
"object",
"object graph"
],
"time": "2020-01-17T21:11:47+00:00"
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2020-06-29T13:22:24+00:00"
},
{
"name": "myclabs/php-enum",
@ -452,16 +458,16 @@
},
{
"name": "opis/closure",
"version": "3.5.5",
"version": "3.5.6",
"source": {
"type": "git",
"url": "https://github.com/opis/closure.git",
"reference": "dec9fc5ecfca93f45cd6121f8e6f14457dff372c"
"reference": "e8d34df855b0a0549a300cb8cb4db472556e8aa9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opis/closure/zipball/dec9fc5ecfca93f45cd6121f8e6f14457dff372c",
"reference": "dec9fc5ecfca93f45cd6121f8e6f14457dff372c",
"url": "https://api.github.com/repos/opis/closure/zipball/e8d34df855b0a0549a300cb8cb4db472556e8aa9",
"reference": "e8d34df855b0a0549a300cb8cb4db472556e8aa9",
"shasum": ""
},
"require": {
@ -509,7 +515,7 @@
"serialization",
"serialize"
],
"time": "2020-06-17T14:59:55+00:00"
"time": "2020-08-11T08:46:50+00:00"
},
{
"name": "phar-io/manifest",
@ -615,24 +621,25 @@
},
{
"name": "php-di/invoker",
"version": "2.0.0",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-DI/Invoker.git",
"reference": "540c27c86f663e20fe39a24cd72fa76cdb21d41a"
"reference": "6a6f8f276d2680e77d06294b9fd67b4881b1f82d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/540c27c86f663e20fe39a24cd72fa76cdb21d41a",
"reference": "540c27c86f663e20fe39a24cd72fa76cdb21d41a",
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/6a6f8f276d2680e77d06294b9fd67b4881b1f82d",
"reference": "6a6f8f276d2680e77d06294b9fd67b4881b1f82d",
"shasum": ""
},
"require": {
"php": ">=7.3",
"psr/container": "~1.0"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"phpunit/phpunit": "~4.5"
"phpunit/phpunit": "^9.0"
},
"type": "library",
"autoload": {
@ -654,20 +661,20 @@
"invoke",
"invoker"
],
"time": "2017-03-20T19:28:22+00:00"
"time": "2020-08-01T15:36:25+00:00"
},
{
"name": "php-di/php-di",
"version": "6.2.1",
"version": "6.2.2",
"source": {
"type": "git",
"url": "https://github.com/PHP-DI/PHP-DI.git",
"reference": "6875fe557c244b3830862c072c7719ca4ac2efe4"
"reference": "40140b5bca07c5fed6919a0f1029ff67617faccd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/6875fe557c244b3830862c072c7719ca4ac2efe4",
"reference": "6875fe557c244b3830862c072c7719ca4ac2efe4",
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/40140b5bca07c5fed6919a0f1029ff67617faccd",
"reference": "40140b5bca07c5fed6919a0f1029ff67617faccd",
"shasum": ""
},
"require": {
@ -726,7 +733,7 @@
"type": "tidelift"
}
],
"time": "2020-06-18T09:54:32+00:00"
"time": "2020-08-23T16:23:17+00:00"
},
{
"name": "php-di/phpdoc-reader",
@ -767,25 +774,25 @@
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.1.0",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
"dev-2.x": "2.x-dev"
}
},
"autoload": {
@ -812,32 +819,31 @@
"reflection",
"static analysis"
],
"time": "2020-04-27T09:25:28+00:00"
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.1.0",
"version": "5.2.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e"
"reference": "d870572532cd70bc3fab58f2e23ad423c8404c44"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d870572532cd70bc3fab58f2e23ad423c8404c44",
"reference": "d870572532cd70bc3fab58f2e23ad423c8404c44",
"shasum": ""
},
"require": {
"ext-filter": "^7.1",
"php": "^7.2",
"phpdocumentor/reflection-common": "^2.0",
"phpdocumentor/type-resolver": "^1.0",
"webmozart/assert": "^1"
"ext-filter": "*",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"doctrine/instantiator": "^1",
"mockery/mockery": "^1"
"mockery/mockery": "~1.3.2"
},
"type": "library",
"extra": {
@ -865,29 +871,28 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2020-02-22T12:28:44+00:00"
"time": "2020-08-15T11:14:08+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.2.0",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "30441f2752e493c639526b215ed81d54f369d693"
"reference": "e878a14a65245fbe78f8080eba03b47c3b705651"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/30441f2752e493c639526b215ed81d54f369d693",
"reference": "30441f2752e493c639526b215ed81d54f369d693",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e878a14a65245fbe78f8080eba03b47c3b705651",
"reference": "e878a14a65245fbe78f8080eba03b47c3b705651",
"shasum": ""
},
"require": {
"php": "^7.2",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "^7.2",
"mockery/mockery": "~1"
"ext-tokenizer": "*"
},
"type": "library",
"extra": {
@ -911,20 +916,20 @@
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"time": "2020-06-19T20:22:09+00:00"
"time": "2020-06-27T10:12:23+00:00"
},
{
"name": "phpmailer/phpmailer",
"version": "v6.1.6",
"version": "v6.1.7",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3"
"reference": "2c2370ba3df7034f9eb7b8f387c97b52b2ba5ad0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3",
"reference": "c2796cb1cb99d7717290b48c4e6f32cb6c60b7b3",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2c2370ba3df7034f9eb7b8f387c97b52b2ba5ad0",
"reference": "2c2370ba3df7034f9eb7b8f387c97b52b2ba5ad0",
"shasum": ""
},
"require": {
@ -979,37 +984,37 @@
"type": "github"
}
],
"time": "2020-05-27T12:24:03+00:00"
"time": "2020-07-14T18:50:27+00:00"
},
{
"name": "phpspec/prophecy",
"version": "v1.10.3",
"version": "1.11.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "451c3cd1418cf640de218914901e51b064abb093"
"reference": "b20034be5efcdab4fb60ca3a29cba2949aead160"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
"reference": "451c3cd1418cf640de218914901e51b064abb093",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/b20034be5efcdab4fb60ca3a29cba2949aead160",
"reference": "b20034be5efcdab4fb60ca3a29cba2949aead160",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
"sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
"sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
"doctrine/instantiator": "^1.2",
"php": "^7.2",
"phpdocumentor/reflection-docblock": "^5.0",
"sebastian/comparator": "^3.0 || ^4.0",
"sebastian/recursion-context": "^3.0 || ^4.0"
},
"require-dev": {
"phpspec/phpspec": "^2.5 || ^3.2",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
"phpspec/phpspec": "^6.0",
"phpunit/phpunit": "^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10.x-dev"
"dev-master": "1.11.x-dev"
}
},
"autoload": {
@ -1042,7 +1047,7 @@
"spy",
"stub"
],
"time": "2020-03-05T15:02:03+00:00"
"time": "2020-07-08T12:44:21+00:00"
},
{
"name": "phpunit/php-code-coverage",
@ -1294,20 +1299,21 @@
"keywords": [
"tokenizer"
],
"abandoned": true,
"time": "2019-09-17T06:23:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "8.5.7",
"version": "8.5.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "809b4bf6754569870c1a93075929bae5615d5ee2"
"reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/809b4bf6754569870c1a93075929bae5615d5ee2",
"reference": "809b4bf6754569870c1a93075929bae5615d5ee2",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34c18baa6a44f1d1fbf0338907139e9dce95b997",
"reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997",
"shasum": ""
},
"require": {
@ -1387,7 +1393,7 @@
"type": "github"
}
],
"time": "2020-06-21T06:32:54+00:00"
"time": "2020-06-22T07:06:58+00:00"
},
{
"name": "psr/container",
@ -2395,30 +2401,31 @@
},
{
"name": "slim/psr7",
"version": "1.1.0",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim-Psr7.git",
"reference": "3c76899e707910779f13d7af95fde12310b0a5ae"
"reference": "832912cb3c2a807d472ef0ac392552e85703a667"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/3c76899e707910779f13d7af95fde12310b0a5ae",
"reference": "3c76899e707910779f13d7af95fde12310b0a5ae",
"url": "https://api.github.com/repos/slimphp/Slim-Psr7/zipball/832912cb3c2a807d472ef0ac392552e85703a667",
"reference": "832912cb3c2a807d472ef0ac392552e85703a667",
"shasum": ""
},
"require": {
"fig/http-message-util": "^1.1.2",
"fig/http-message-util": "^1.1.4",
"php": "^7.2",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0",
"ralouphie/getallheaders": "^3"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"adriansuter/php-autoload-override": "^1.0",
"adriansuter/php-autoload-override": "^1.2",
"ext-json": "*",
"http-interop/http-factory-tests": "^0.6.0",
"php-http/psr7-integration-tests": "dev-master",
@ -2465,7 +2472,7 @@
"psr-7",
"psr7"
],
"time": "2020-05-01T14:24:20+00:00"
"time": "2020-08-18T22:49:11+00:00"
},
{
"name": "slim/slim",
@ -2572,16 +2579,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.17.0",
"version": "v1.18.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454",
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454",
"shasum": ""
},
"require": {
@ -2593,7 +2600,11 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
"dev-master": "1.18-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@ -2640,27 +2651,27 @@
"type": "tidelift"
}
],
"time": "2020-05-12T16:14:59+00:00"
"time": "2020-07-14T12:35:20+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.1.3",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
"reference": "75a63c33a8577608444246075ea0af0d052e452a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
"reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a",
"reference": "75a63c33a8577608444246075ea0af0d052e452a",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.0"
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
@ -2680,24 +2691,30 @@
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"time": "2019-06-13T22:48:21+00:00"
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2020-07-12T23:59:07+00:00"
},
{
"name": "webmozart/assert",
"version": "1.9.0",
"version": "1.9.1",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "9dc4f203e36f2b486149058bade43c851dd97451"
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451",
"reference": "9dc4f203e36f2b486149058bade43c851dd97451",
"url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0",
"php": "^5.3.3 || ^7.0 || ^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
@ -2729,7 +2746,7 @@
"check",
"validate"
],
"time": "2020-06-16T10:16:42+00:00"
"time": "2020-07-08T17:02:28+00:00"
}
],
"packages-dev": [],

View File

@ -217,48 +217,15 @@ class Auth extends BaseController {
return $this->jsonResponse($response);
}
public function refreshToken($request, $response) {
$response = self::ValidateToken($request, $response);
$status = $response->getStatusCode();
if ($status !== 200) {
if ($status === 400) {
$this->apiJson->addAlert('error',
'Authorization header missing.');
return $this->jsonResponse($response, $status);
}
$this->apiJson->addAlert('error', 'Invalid API token.');
return $this->jsonResponse($response, $status);
}
$jwt = $request->getHeader('Authorization')[0];
$payload = self::getJwtPayload($jwt);
$user = R::load('user', $payload->uid);
$jwt = self::createJwt($user->id, (int)$payload->mul);
$user->active_token = $jwt;
R::store($user);
$opts = R::load('useroption', $user->user_option_id);
$this->apiJson->setSuccess();
$this->apiJson->addData($jwt);
$this->apiJson->addData($this->sanitizeUser($user));
$this->apiJson->addData($opts);
return $this->jsonResponse($response);
public static function createJwt($userId, $mult = 1) {
return JWT::encode(array(
'exp' => time() + (60 * 30) * $mult, // 30 minutes * $mult
'uid' => (int)$userId,
'mul' => $mult
), Auth::getJwtKey());
}
private function sanitizeUser($user) {
unset($user->password_hash);
unset($user->active_token);
return $user;
}
private static function getJwtPayload($jwt) {
public static function getJwtPayload($jwt) {
try {
$payload = JWT::decode($jwt, self::getJwtKey(), ['HS256']);
} catch (Exception $ex) {
@ -268,16 +235,11 @@ class Auth extends BaseController {
return $payload;
}
private static function createJwt($userId, $mult = 1) {
// If 'remember me' feature is desired, set the multiplier higher.
// By default, a token will expire after half an hour, but can be
// refreshed by a call to /api/refresh.
private function sanitizeUser($user) {
unset($user->password_hash);
unset($user->active_token);
return JWT::encode(array(
'exp' => time() + (60 * 30) * $mult, // 30 minutes * $mult
'uid' => (int)$userId,
'mul' => $mult
), Auth::getJwtKey());
return $user;
}
private static function getJwtKey() {

View File

@ -67,8 +67,13 @@ abstract class BaseController {
return 403;
}
$payload = Auth::getJwtPayload($request->getHeader('Authorization')[0]);
$user->active_token = Auth::createJwt($user->id, $payload->mul);
R::store($user);
$this->setStrings($user->userOptionId);
$this->apiJson->addData($request->getHeader('Authorization'));
$this->apiJson->addData($user->active_token);
return $status;
}

View File

@ -113,6 +113,7 @@ class Columns extends BaseController {
$this->apiJson->addAlert('success', $this->strings->api_columnUpdated .
'(' . $update->name . ').');
$this->apiJson->addData(R::exportAll($update));
$this->apiJson->addData(R::exportAll(R::load('board', $update->board_id)));
return $this->jsonResponse($response);
}

View File

@ -111,11 +111,10 @@ class Tasks extends BaseController {
$before = R::exportAll($task);
R::store($update);
$after= R::exportAll($update);
$after = R::exportAll($update);
$actor = R::load('user', Auth::GetUserId($request));
$this->updateTaskOrder($update, $actor, false);
$this->checkAutomaticActions($before, $after);
$update = R::load('task', $update->id);
@ -189,7 +188,7 @@ class Tasks extends BaseController {
}
private function sortTasks($a, $b) {
return strcmp($a->position, $b->position);
return (int)$a->position - (int)$b->position;
}
private function updateTaskOrder($task, $user, $isNew) {
@ -199,8 +198,8 @@ class Tasks extends BaseController {
usort($column->xownTaskList, array($this, 'sortTasks'));
$counter = 1;
foreach ($column->xownTaskList as $task) {
$task->position = $counter;
foreach ($column->xownTaskList as $taskP) {
$taskP->position = $counter;
$counter++;
}

View File

@ -104,7 +104,6 @@ $app->get('/activity[/{type}[/{id}]]', 'Activity:getActivity'); // BoardAdmin (w
$app->post('/login', 'Auth:login'); // Unsecured (creates JWT)
$app->post('/logout', 'Auth:logout'); // Unsecured (clears JWT)
$app->post('/authenticate', 'Auth:authenticate'); // Unsecured (checks JWT)
$app->post('/refresh', 'Auth:refreshToken'); // Unsecured (checks and updates JWT)
$app->get('/dashboard/boards', 'Dashboard:getMyBoardInfo'); // User (by board access)
$app->get('/dashboard/tasks', 'Dashboard:getMyTaskInfo'); // User (by board access)

View File

@ -75,9 +75,8 @@
<h1>{{ strings['boards_noDefault'] }}</h1>
<p>{{ strings['boards_noDefaultMessage'] }}
<a href="javascript:" [routerLink]="['/settings']">
{{ strings['settings'] }}
</a>.
<a href="javascript:"
[routerLink]="['/settings']">{{ strings['settings'] }}</a>.
</p>
<p></p>

View File

@ -152,17 +152,15 @@ export class BoardDisplayComponent implements OnInit, OnDestroy {
}
updateBoards(): void {
this.boardService.refreshToken(() => {
this.boardService.getBoards().subscribe((response: ApiResponse) => {
this.boards = [];
this.boardService.getBoards().subscribe((response: ApiResponse) => {
this.boards = [];
if (response.data.length > 1) {
this.updateBoardsList(response.data[1]);
return;
}
if (response.data.length > 1) {
this.updateBoardsList(response.data[1]);
return;
}
this.loading = false;
});
this.loading = false;
});
}

View File

@ -186,10 +186,6 @@ export class BoardService extends ApiService {
)
}
refreshToken(callback: any): void {
this.http.post(this.apiBase + 'refresh', {}).subscribe(() => callback());
}
private async convertBoardData(boardData: any): Promise<Board> {
if (boardData instanceof Board) {
return boardData;

View File

@ -295,35 +295,20 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
event.container.data, event.previousIndex, event.currentIndex);
}
const colId = (event.container.element.nativeElement.id).substring(3);
const colIndex = this.activeBoard.columns.findIndex(col => +col.id === +colId);
const colId = event.container.id.substr(3) as unknown as number - 1;
const column = this.activeBoard.columns[colId];
this.activeBoard.columns[colIndex].tasks.forEach((item, index) => {
item.position = index + 1;
item.column_id = this.activeBoard.columns[colIndex].id;
column.tasks.forEach((task, index) => {
task.position = index + 1;
});
const task = this.activeBoard.columns[colIndex].tasks[event.currentIndex];
this.boardService.updateTask(task).subscribe((response: ApiResponse) => {
response.alerts.forEach(alert => {
if (alert.type === 'success') {
return; // No need to show "task updated" for drag and drop
}
this.notes.add(alert);
});
this.boardService.updateColumn(column).subscribe((response: ApiResponse) => {
if (response.status !== 'success') {
response.alerts.forEach(note => this.notes.add(note));
return;
}
const newTask = response.data[1][0];
const updatedTask = new Task(newTask.id, newTask.title, newTask.description,
newTask.color, newTask.due_date, newTask.points,
newTask.position, newTask.column_id, newTask.ownComment,
newTask.ownAttachment, newTask.sharedUser, newTask.sharedCategory);
this.activeBoard.columns[colIndex].tasks[event.currentIndex] = updatedTask;
this.boardService.updateActiveBoard(response.data[2][0]);
});
}

View File

@ -3,17 +3,17 @@
"short_name": "TaskBoard",
"icons": [
{
"src": "/favicons/android-chrome-192x192.png",
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/favicons/android-chrome-512x512.png",
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"theme_color": "#dbe9ee",
"background_color": "#dbe9ee",
"display": "standalone"
}

View File

@ -16,13 +16,13 @@
"logout": "Cerrar Sesión",
"settings_userSettings": "Mi Configuración",
"settings_changePassword": "Cambia Contraseña",
"settings_changePassword": "Cambiar Contraseña",
"settings_currentPassword": "Contraseña Actual",
"settings_newPassword": "Contraseña Nueva",
"settings_verifyPassword": "Verficar Contraseña",
"settings_changeUsername": "Cambia Nombre de Usuario",
"settings_changeUsername": "Cambiar Nombre de Usuario",
"settings_newUsername": "Nuevo Nombre de Usuario",
"settings_changeEmail": "Cambia Email",
"settings_changeEmail": "Cambiar Email",
"settings_newEmail": "Nuevo Email",
"settings_blank": "En blanco para desactivar",
"settings_globalOptions": "Opciones Globales",
@ -44,7 +44,7 @@
"settings_edit": "Editar",
"settings_removeUser": "Eliminar Usuario",
"settings_addUser": "Agregar Usuario",
"settings_editUser": "Cambia Usuario",
"settings_editUser": "Cambiar Usuario",
"settings_saveUser": "Guardar Usuario",
"settings_confirmUserRemoval": "Confirmar Eliminación del Usuario",
"settings_removeUserWarning": "No se puede deshacer la eliminación de un usuario.",
@ -75,7 +75,7 @@
"settings_columns": "Columnas",
"settings_categories": "Categorías",
"settings_users": "Usuarios",
"settings_editBoard": "Cambia Tablero",
"settings_editBoard": "Cambiar Tablero",
"settings_addBoard": "Agregar Tablero",
"settings_removeBoard": "Eliminar Tablero",
"settings_confirmBoardRemoval": "Confirmar Eliminación del Tablero",

View File

@ -232,45 +232,5 @@ class AuthTest extends PHPUnit\Framework\TestCase {
$this->assertEquals('failure', $actual->body->data->status);
}
public function testRefreshToken() {
$data = new stdClass();
$data->username = 'admin';
$data->password = 'admin';
$data->remember = false;
$request = new RequestMock();
$request->payload = $data;
Auth::CreateInitialAdmin(new LoggerMock());
Auth::CreateJwtSigningKey();
$actual = $this->auth->login($request, new ResponseMock(), null);
$this->assertEquals('success', $actual->body->data->status);
$jwt = $actual->body->data->data[0];
$this->auth = new Auth(new LoggerMock());
$request = new RequestMock();
$request->header = [$jwt];
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
$user = R::load('user', 1);
$this->assertEquals('success', $actual->body->data->status);
$this->assertEquals($user->active_token, $actual->body->data->data[0]);
$this->auth = new Auth(new LoggerMock());
$request->hasHeader = false;
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
$this->assertEquals('failure', $actual->body->data->status);
$this->auth = new Auth(new LoggerMock());
$request = new RequestMock();
$request->header = ['not a valid JWT'];
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
$this->assertEquals('failure', $actual->body->data->status);
}
}

View File

@ -371,7 +371,7 @@ class TasksTest extends PHPUnit\Framework\TestCase {
$action = R::dispense('autoaction');
$action->board_id = 1;
$action->trigger = 1; // Moved to column
$action->source_id = 1; // Category ID
$action->source_id = 1; // Column ID
$action->type = 6; // Clear due date
$action->change_to = 0;

View File

@ -287,10 +287,5 @@ describe('BoardService', () => {
testCall('api/upload/asdf', 'POST', true);
});
it('refreshes the API token', () => {
service.refreshToken(() => {});
testCall('api/refresh', 'POST');
});
});

View File

@ -193,9 +193,7 @@ describe('ColumnDisplay', () => {
it('handles drop events', () => {
const prev = {
data: {},
element: {
nativeElement: { id: 'col1' }
}
id: 'col1'
};
const evt = {
currentIndex: 0,
@ -214,9 +212,7 @@ describe('ColumnDisplay', () => {
evt.previousContainer = {
data: {},
element: {
nativeElement: { id: 'col1' }
}
id: 'col1'
};
component.drop(evt as any);