Build should pass again
This commit is contained in:
parent
e6233405ff
commit
515765e296
1
.gitignore
vendored
1
.gitignore
vendored
@ -34,6 +34,7 @@ npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
.phpunit.result.cache
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
|
570
package-lock.json
generated
570
package-lock.json
generated
@ -5,12 +5,12 @@
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": {
|
||||
"version": "0.803.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.21.tgz",
|
||||
"integrity": "sha512-E2K/YexIWVyKM/xmyxvDjkJf+wX9u4c8YYpNaK4htsRzA06juc7N1MhlL/jURZiRl5b/K9sapYeq3tMX76saxA==",
|
||||
"version": "0.803.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.22.tgz",
|
||||
"integrity": "sha512-5Gr0LH+Hjd/NLdmi660VBoo3WbzQM7/yeG+ziktb7hbeVaYK4Mejtcg/DJnCoZ3hzlZuZokWVwvpdFo+A9xKbg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"rxjs": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -26,23 +26,23 @@
|
||||
}
|
||||
},
|
||||
"@angular-devkit/build-angular": {
|
||||
"version": "0.803.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.21.tgz",
|
||||
"integrity": "sha512-flfgflvfpwdsm3x/U7QnfbtyZPEbsVipzQAoao1Zo58Beq1a+NsKsWbjrF/x4TSoI2czt0OVWXNytlfXM7LMhg==",
|
||||
"version": "0.803.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.22.tgz",
|
||||
"integrity": "sha512-2q9qLsD52D4GACUAuQhvkgQ7vLAhZzdU0jzfs74RTxqUZ3PS6Ltrrwpdg2kp9RlQ53+nSCYjWBDLk1CxoEt4pg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/architect": "0.803.21",
|
||||
"@angular-devkit/build-optimizer": "0.803.21",
|
||||
"@angular-devkit/build-webpack": "0.803.21",
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/architect": "0.803.22",
|
||||
"@angular-devkit/build-optimizer": "0.803.22",
|
||||
"@angular-devkit/build-webpack": "0.803.22",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"@babel/core": "7.7.5",
|
||||
"@babel/preset-env": "7.7.6",
|
||||
"@ngtools/webpack": "8.3.21",
|
||||
"@ngtools/webpack": "8.3.22",
|
||||
"ajv": "6.10.2",
|
||||
"autoprefixer": "9.6.1",
|
||||
"browserslist": "4.6.6",
|
||||
"browserslist": "4.8.3",
|
||||
"cacache": "12.0.2",
|
||||
"caniuse-lite": "1.0.30000989",
|
||||
"caniuse-lite": "1.0.30001019",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
"clean-css": "4.2.1",
|
||||
"copy-webpack-plugin": "5.1.1",
|
||||
@ -119,9 +119,9 @@
|
||||
}
|
||||
},
|
||||
"@angular-devkit/build-optimizer": {
|
||||
"version": "0.803.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.21.tgz",
|
||||
"integrity": "sha512-gNN6kPaF4phZco3TmsrNr9tIEKXYsoSeoaUiDUfgmCYwa7fAqM8Ojh7HX6IQuB2PpVmEwKGlCcSh6xDtB33NjA==",
|
||||
"version": "0.803.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.22.tgz",
|
||||
"integrity": "sha512-VIDeQcBn88PjHBTen3BRVA7DJiKEJdDwukx61mUvUDOcY7S5Ot5WqG0nrZifRjha17Z+fl3XuwS9TZNYmlF7WQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "1.2.3",
|
||||
@ -146,13 +146,13 @@
|
||||
}
|
||||
},
|
||||
"@angular-devkit/build-webpack": {
|
||||
"version": "0.803.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.21.tgz",
|
||||
"integrity": "sha512-zCFVla/Xdk8qGVybvnHtoKml2h0/ShasSjT55VNZO1XaTCMqYkQEwwqSGEiVajpauafWjKrKxxBhsmWoI4efAA==",
|
||||
"version": "0.803.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.22.tgz",
|
||||
"integrity": "sha512-RDLAhKHfTFzthzeawHEefYB1MxHiU2I32QzXI3XTCpR2XySw5JG9jIVIcsyDHQH1JtIfpHGq8vgfiTsE3r0YWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/architect": "0.803.21",
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/architect": "0.803.22",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"rxjs": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -168,9 +168,9 @@
|
||||
}
|
||||
},
|
||||
"@angular-devkit/core": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.21.tgz",
|
||||
"integrity": "sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA==",
|
||||
"version": "8.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.22.tgz",
|
||||
"integrity": "sha512-lOEYcvK3MktjR9YZT/cUjiQE5dZxl8rZ/vgWgwDiL7RtzfXTt8lPapoJe7YKS53gLbUYiBNPCtTyTAqnslWgGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "6.10.2",
|
||||
@ -198,28 +198,15 @@
|
||||
}
|
||||
},
|
||||
"@angular-devkit/schematics": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.21.tgz",
|
||||
"integrity": "sha512-+wH0362CRr/SijVX4w2baY2ANZ4scQ1k2xO8lT+NMeZQkw3IJQPOfwk1IaqiAs2xuBJZcSDH1Gn80+Jh4Dit7w==",
|
||||
"version": "8.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.22.tgz",
|
||||
"integrity": "sha512-ETLdV1ftT+ZuuiHl6FjFQ4XLQznWMcxWognX+qgByn+DQOXsYRRvZK1L5eG/SG8CKJ8NL5oteTDloDnghARHFw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"rxjs": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.21.tgz",
|
||||
"integrity": "sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "6.10.2",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"magic-string": "0.25.3",
|
||||
"rxjs": "6.4.0",
|
||||
"source-map": "0.7.3"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
|
||||
@ -228,12 +215,6 @@
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -246,16 +227,16 @@
|
||||
}
|
||||
},
|
||||
"@angular/cli": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.21.tgz",
|
||||
"integrity": "sha512-ZZpA7mMfIobFT06rBNxm8vucAh8W2s0huJZ4iL0BPujnhIr71PL+gDwssySWDEz2q6i4CkH9QRH76DHhtL6VSQ==",
|
||||
"version": "8.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.22.tgz",
|
||||
"integrity": "sha512-OT2rzwnxwI0ETP7rXCxjxsIAZEYo9wHP/5rRbu3m15GlQ3Bclq34ZDRwC/bRxXL5+1DfmhAs9AjtYNoFoDM4Tg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/architect": "0.803.21",
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/schematics": "8.3.21",
|
||||
"@schematics/angular": "8.3.21",
|
||||
"@schematics/update": "0.803.21",
|
||||
"@angular-devkit/architect": "0.803.22",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"@angular-devkit/schematics": "8.3.22",
|
||||
"@schematics/angular": "8.3.22",
|
||||
"@schematics/update": "0.803.22",
|
||||
"@yarnpkg/lockfile": "1.1.0",
|
||||
"ansi-colors": "4.1.1",
|
||||
"debug": "^4.1.1",
|
||||
@ -273,29 +254,6 @@
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": {
|
||||
"version": "0.803.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.21.tgz",
|
||||
"integrity": "sha512-E2K/YexIWVyKM/xmyxvDjkJf+wX9u4c8YYpNaK4htsRzA06juc7N1MhlL/jURZiRl5b/K9sapYeq3tMX76saxA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"rxjs": "6.4.0"
|
||||
}
|
||||
},
|
||||
"@angular-devkit/core": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.21.tgz",
|
||||
"integrity": "sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "6.10.2",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"magic-string": "0.25.3",
|
||||
"rxjs": "6.4.0",
|
||||
"source-map": "0.7.3"
|
||||
}
|
||||
},
|
||||
"ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
@ -326,26 +284,11 @@
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
|
||||
"integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2187,12 +2130,12 @@
|
||||
}
|
||||
},
|
||||
"@ngtools/webpack": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.21.tgz",
|
||||
"integrity": "sha512-DGqmFQ52sV4uB3y3spQTNLa69oU5cwd1yIqMB4GSM+Qp+hozdzrPA2gVH90N2DDhWe8icsSQHAtZQiR9+BDL8g==",
|
||||
"version": "8.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.22.tgz",
|
||||
"integrity": "sha512-MES7Q0k6GpQEY74cxElUVy7jIaDBSLvY+eOUN2GKL5CznvBSp3+U5px6X7ZjPGzCp7no1L1JkV9g2e0hPatlcw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"enhanced-resolve": "4.1.0",
|
||||
"rxjs": "6.4.0",
|
||||
"tree-kill": "1.2.1",
|
||||
@ -2211,53 +2154,23 @@
|
||||
}
|
||||
},
|
||||
"@schematics/angular": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.21.tgz",
|
||||
"integrity": "sha512-KahQ+dHvTsGOZwY6IdzqJZLDEn0G89rrK3OY+7okZujoaLM+LXhxlPoznW1udnZJVTa3VNxYGx11fkgLtRJRqA==",
|
||||
"version": "8.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.22.tgz",
|
||||
"integrity": "sha512-vD+UgPdbEoFPOH6xe2laFpHn/MC9R5C4A/+J9yQ6HBg5kt1YdyIBakvPOcXQCyWr5VZzDmTyMO76rd3zaef3DQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/schematics": "8.3.21"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.21.tgz",
|
||||
"integrity": "sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "6.10.2",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"magic-string": "0.25.3",
|
||||
"rxjs": "6.4.0",
|
||||
"source-map": "0.7.3"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
|
||||
"integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
}
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"@angular-devkit/schematics": "8.3.22"
|
||||
}
|
||||
},
|
||||
"@schematics/update": {
|
||||
"version": "0.803.21",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.21.tgz",
|
||||
"integrity": "sha512-D3BRvEBF2cJEgogvFaNOfqtTFHHv/ctSRfOeAYWjUxILtb+2DpuZ9h5QYDFhN9MPgz/vRaOqFORa3sEZCRkX4g==",
|
||||
"version": "0.803.22",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.22.tgz",
|
||||
"integrity": "sha512-X+1sJ7YadcYxDqcLX7l7MEAIL3SHIXpCqToQdAZbAE06NdTFvg5eqiKreSdmm7ZdfL0dBe6oXi/yCDVMoL2zcw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@angular-devkit/core": "8.3.21",
|
||||
"@angular-devkit/schematics": "8.3.21",
|
||||
"@angular-devkit/core": "8.3.22",
|
||||
"@angular-devkit/schematics": "8.3.22",
|
||||
"@yarnpkg/lockfile": "1.1.0",
|
||||
"ini": "1.3.5",
|
||||
"pacote": "9.5.5",
|
||||
@ -2266,19 +2179,6 @@
|
||||
"semver-intersect": "1.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": {
|
||||
"version": "8.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.21.tgz",
|
||||
"integrity": "sha512-BYyVbrbys535FplX0+GVOlYBg/cyk1U5SRhSxRRFZYi9epVlEBBPk8/6wV4cQPGb6EwXkVj7YtPWXjXcGfzWmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "6.10.2",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"magic-string": "0.25.3",
|
||||
"rxjs": "6.4.0",
|
||||
"source-map": "0.7.3"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
|
||||
@ -2293,12 +2193,6 @@
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2364,9 +2258,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.12.22",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.22.tgz",
|
||||
"integrity": "sha512-r5i93jqbPWGXYXxianGATOxTelkp6ih/U0WVnvaqAvTqM+0U6J3kw6Xk6uq/dWNRkEVw/0SLcO5ORXbVNz4FMQ==",
|
||||
"version": "13.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.6.tgz",
|
||||
"integrity": "sha512-Jg1F+bmxcpENHP23sVKkNuU3uaxPnsBMW0cLjleiikFKomJQbsn0Cqk2yDvQArqzZN6ABfBkZ0To7pQ8sLdWDg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/q": {
|
||||
@ -2753,14 +2647,6 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"type-fest": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ansi-html": {
|
||||
@ -3650,14 +3536,14 @@
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.6.6",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
|
||||
"integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
|
||||
"version": "4.8.3",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.3.tgz",
|
||||
"integrity": "sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30000984",
|
||||
"electron-to-chromium": "^1.3.191",
|
||||
"node-releases": "^1.1.25"
|
||||
"caniuse-lite": "^1.0.30001017",
|
||||
"electron-to-chromium": "^1.3.322",
|
||||
"node-releases": "^1.1.44"
|
||||
}
|
||||
},
|
||||
"browserstack": {
|
||||
@ -3858,9 +3744,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30000989",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz",
|
||||
"integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==",
|
||||
"version": "1.0.30001019",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz",
|
||||
"integrity": "sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g==",
|
||||
"dev": true
|
||||
},
|
||||
"canonical-path": {
|
||||
@ -3925,9 +3811,9 @@
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz",
|
||||
"integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==",
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
|
||||
"integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==",
|
||||
"dev": true
|
||||
},
|
||||
"chrome-trace-event": {
|
||||
@ -4162,18 +4048,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"compressible": {
|
||||
"version": "2.0.17",
|
||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
|
||||
"integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||
"integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": ">= 1.40.0 < 2"
|
||||
"mime-db": ">= 1.43.0 < 2"
|
||||
},
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.42.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
|
||||
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==",
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@ -4454,37 +4340,20 @@
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.1.tgz",
|
||||
"integrity": "sha512-186WjSik2iTGfDjfdCZAxv2ormxtKgemjC3SI6PL31qOA0j5LhTDVjHChccoc7brwLvpvLPiMyRlcO88C4l1QQ=="
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.3.tgz",
|
||||
"integrity": "sha512-DOO9b18YHR+Wk5kJ/c5YFbXuUETreD4TrvXb6edzqZE3aAEd0eJIAWghZ9HttMuiON8SVCnU3fqA4rPxRDD1HQ=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.0.tgz",
|
||||
"integrity": "sha512-Z3eCNjGgoYluH89Jt4wVkfYsc/VdLrA2/woX5lm0isO/pCT+P+Y+o65bOuEnjDJLthdwTBxbCVzptTXtc18fJg==",
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.3.tgz",
|
||||
"integrity": "sha512-Y3YNGU3bU1yrnzVodop23ghArbKv4IqkZg9MMOWv/h7KT6NRk1/SzHhWDDlubg2+tlcUzAqgj1/GyeJ9fUKMeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browserslist": "^4.8.2",
|
||||
"browserslist": "^4.8.3",
|
||||
"semver": "7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"browserslist": {
|
||||
"version": "4.8.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.2.tgz",
|
||||
"integrity": "sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001015",
|
||||
"electron-to-chromium": "^1.3.322",
|
||||
"node-releases": "^1.1.42"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001016",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz",
|
||||
"integrity": "sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
|
||||
@ -4690,9 +4559,9 @@
|
||||
"integrity": "sha1-LkYovhncSyFLXAJjDFlx6BFhgGI="
|
||||
},
|
||||
"cyclist": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
|
||||
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
|
||||
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
|
||||
"dev": true
|
||||
},
|
||||
"damerau-levenshtein": {
|
||||
@ -5090,9 +4959,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.322",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz",
|
||||
"integrity": "sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==",
|
||||
"version": "1.3.331",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.331.tgz",
|
||||
"integrity": "sha512-GuDv5gkxwRROYnmIVFUohoyrNapWCKLNn80L7Pa+9WRF/oY4t7XLH7wBMsYBgIRwi8BvEvsGKLKh8kOciOp6kA==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
@ -5355,9 +5224,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"events": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
|
||||
"integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
|
||||
"integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
|
||||
"dev": true
|
||||
},
|
||||
"eventsource": {
|
||||
@ -5924,12 +5793,12 @@
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz",
|
||||
"integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==",
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
|
||||
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minipass": "^2.2.1"
|
||||
"minipass": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"fs-write-stream-atomic": {
|
||||
@ -6540,9 +6409,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"ignore-walk": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
|
||||
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
|
||||
"integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
@ -7550,12 +7419,12 @@
|
||||
}
|
||||
},
|
||||
"karma-jasmine": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz",
|
||||
"integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-3.1.0.tgz",
|
||||
"integrity": "sha512-IVGbC8gap5x5NNCEOsAE77ic8rZtHDt6wmO0fFC5yT5FeB8qKnGTeud2mtKyQ41xl7vZkZ7ZxKr4wMGR6tWN+A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jasmine-core": "^3.3"
|
||||
"jasmine-core": "^3.5.0"
|
||||
}
|
||||
},
|
||||
"karma-jasmine-html-reporter": {
|
||||
@ -7827,16 +7696,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"make-fetch-happen": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.0.tgz",
|
||||
"integrity": "sha512-nFr/vpL1Jc60etMVKeaLOqfGjMMb3tAHFVJWxHOFCFS04Zmd7kGlMxo0l1tzfhoQje0/UPnd0X8OeGUiXXnfPA==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz",
|
||||
"integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"agentkeepalive": "^3.4.1",
|
||||
"cacache": "^12.0.0",
|
||||
"http-cache-semantics": "^3.8.1",
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
"https-proxy-agent": "^2.2.1",
|
||||
"https-proxy-agent": "^2.2.3",
|
||||
"lru-cache": "^5.1.1",
|
||||
"mississippi": "^3.0.0",
|
||||
"node-fetch-npm": "^2.0.2",
|
||||
@ -7845,35 +7714,6 @@
|
||||
"ssri": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cacache": {
|
||||
"version": "12.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
|
||||
"integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird": "^3.5.5",
|
||||
"chownr": "^1.1.1",
|
||||
"figgy-pudding": "^3.5.1",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.1.15",
|
||||
"infer-owner": "^1.0.3",
|
||||
"lru-cache": "^5.1.1",
|
||||
"mississippi": "^3.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"move-concurrently": "^1.0.1",
|
||||
"promise-inflight": "^1.0.1",
|
||||
"rimraf": "^2.6.3",
|
||||
"ssri": "^6.0.1",
|
||||
"unique-filename": "^1.1.1",
|
||||
"y18n": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
|
||||
"integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -7883,16 +7723,10 @@
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
|
||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@ -8194,9 +8028,9 @@
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
|
||||
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
|
||||
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
@ -8204,20 +8038,20 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
|
||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
|
||||
"integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
|
||||
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minipass": "^2.2.1"
|
||||
"minipass": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"mississippi": {
|
||||
@ -8441,9 +8275,9 @@
|
||||
}
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "1.1.43",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.43.tgz",
|
||||
"integrity": "sha512-Rmfnj52WNhvr83MvuAWHEqXVoZXCcDQssSOffU4n4XOL9sPrP61mSZ88g25NqmABDvH7PiAlFCzoSCSdzA293w==",
|
||||
"version": "1.1.45",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.45.tgz",
|
||||
"integrity": "sha512-cXvGSfhITKI8qsV116u2FTzH5EWZJfgG7d4cpqwF8I8+1tWpD6AsvvGRKq2onR0DNj1jfqsjkXZsm14JMS7Cyg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.3.0"
|
||||
@ -8658,10 +8492,13 @@
|
||||
}
|
||||
},
|
||||
"npm-bundled": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
|
||||
"integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
|
||||
"dev": true
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
|
||||
"integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
@ -8682,9 +8519,9 @@
|
||||
}
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.4.tgz",
|
||||
"integrity": "sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw==",
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz",
|
||||
"integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
@ -8703,9 +8540,9 @@
|
||||
}
|
||||
},
|
||||
"npm-registry-fetch": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz",
|
||||
"integrity": "sha512-Jllq35Jag8dtv0M17ue74XtdQTyqKzuAYGiX9mAjOhkmNjib3bBUgK6mUY61+AHnXeSRobQkpY3/xIOS/omptw==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz",
|
||||
"integrity": "sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"JSONStream": "^1.3.4",
|
||||
@ -8713,7 +8550,8 @@
|
||||
"figgy-pudding": "^3.4.1",
|
||||
"lru-cache": "^5.1.1",
|
||||
"make-fetch-happen": "^5.0.0",
|
||||
"npm-package-arg": "^6.1.0"
|
||||
"npm-package-arg": "^6.1.0",
|
||||
"safe-buffer": "^5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
@ -8725,10 +8563,16 @@
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
|
||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@ -8976,22 +8820,22 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.17.0-next.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz",
|
||||
"integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==",
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0.tgz",
|
||||
"integrity": "sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.1.4",
|
||||
"is-regex": "^1.0.4",
|
||||
"is-callable": "^1.1.5",
|
||||
"is-regex": "^1.0.5",
|
||||
"object-inspect": "^1.7.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.0",
|
||||
"string.prototype.trimleft": "^2.1.0",
|
||||
"string.prototype.trimright": "^2.1.0"
|
||||
"string.prototype.trimleft": "^2.1.1",
|
||||
"string.prototype.trimright": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"es-to-primitive": {
|
||||
@ -9010,6 +8854,21 @@
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
|
||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
|
||||
"integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
|
||||
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -9274,18 +9133,6 @@
|
||||
"mkdirp": "^0.5.0",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
|
||||
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
@ -9303,12 +9150,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"parallel-transform": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
|
||||
"integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
|
||||
"integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cyclist": "~0.2.2",
|
||||
"cyclist": "^1.0.1",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^2.1.5"
|
||||
}
|
||||
@ -10261,22 +10108,22 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.17.0-next.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz",
|
||||
"integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==",
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0.tgz",
|
||||
"integrity": "sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.1.4",
|
||||
"is-regex": "^1.0.4",
|
||||
"is-callable": "^1.1.5",
|
||||
"is-regex": "^1.0.5",
|
||||
"object-inspect": "^1.7.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.0",
|
||||
"string.prototype.trimleft": "^2.1.0",
|
||||
"string.prototype.trimright": "^2.1.0"
|
||||
"string.prototype.trimleft": "^2.1.1",
|
||||
"string.prototype.trimright": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"es-to-primitive": {
|
||||
@ -10295,6 +10142,21 @@
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
|
||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
|
||||
"integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
|
||||
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -10338,9 +10200,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"regjsparser": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.1.tgz",
|
||||
"integrity": "sha512-7LutE94sz/NKSYegK+/4E77+8DipxF+Qn2Tmu362AcmsF2NYq/wx3+ObvU90TKEhjf7hQoFXo23ajjrXP7eUgg==",
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.2.tgz",
|
||||
"integrity": "sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsesc": "~0.5.0"
|
||||
@ -10897,9 +10759,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"smart-buffer": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz",
|
||||
"integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz",
|
||||
"integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==",
|
||||
"dev": true
|
||||
},
|
||||
"snapdragon": {
|
||||
@ -11158,13 +11020,13 @@
|
||||
}
|
||||
},
|
||||
"socks": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz",
|
||||
"integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==",
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz",
|
||||
"integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ip": "^1.1.5",
|
||||
"smart-buffer": "4.0.2"
|
||||
"ip": "1.1.5",
|
||||
"smart-buffer": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"socks-proxy-agent": {
|
||||
@ -11502,9 +11364,9 @@
|
||||
}
|
||||
},
|
||||
"stream-shift": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
|
||||
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
|
||||
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
|
||||
"dev": true
|
||||
},
|
||||
"streamroller": {
|
||||
@ -12001,16 +11863,16 @@
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "8.5.4",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.4.tgz",
|
||||
"integrity": "sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw==",
|
||||
"version": "8.6.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.6.1.tgz",
|
||||
"integrity": "sha512-KqPbO7/UuOPE4ANAOV9geZjk6tet6rK2K+DFeEJq6kIXUi0nLkrOMksozGkIlFopOorkStlwar3DdWYrdl7zCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arg": "^4.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"source-map-support": "^0.5.6",
|
||||
"yn": "^3.0.0"
|
||||
"yn": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
@ -12099,6 +11961,12 @@
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"dev": true
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
@ -14615,9 +14483,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-4.0.0.tgz",
|
||||
"integrity": "sha512-huWiiCS4TxKc4SfgmTwW1K7JmXPPAmuXWYy4j9qjQo4+27Kni8mGhAAi1cloRWmBe2EqcLgt3IGqQoRL/MtPgg==",
|
||||
"dev": true
|
||||
},
|
||||
"zone.js": {
|
||||
|
14
package.json
14
package.json
@ -34,7 +34,7 @@
|
||||
"test": "npm-run-all test:app test:api",
|
||||
"test:app": "ng test --code-coverage --watch=false",
|
||||
"test:api": "./src/api/vendor/phpunit/phpunit/phpunit -c test/api/phpunit.xml",
|
||||
"test:api-single": "./src/api/vendor/phpunit/phpunit/phpunit -c test/api/phpunit.xml -g single",
|
||||
"test:api-single": "./src/api/vendor/phpunit/phpunit/phpunit -c test/api/phpunit.xml --group single",
|
||||
"test:watch": "ng test --code-coverage --watch",
|
||||
"lint": "ng lint",
|
||||
"postinstall": "cd src/api/ && composer update && composer install --optimize-autoloader && cd ../../"
|
||||
@ -52,7 +52,7 @@
|
||||
"chartist": "^0.11.4",
|
||||
"chartist-plugin-tooltips": "^0.0.17",
|
||||
"classlist.js": "^1.1.20150312",
|
||||
"core-js": "^3.6.1",
|
||||
"core-js": "^3.6.3",
|
||||
"dragula": "^3.7.2",
|
||||
"highlight.js": "^9.17.1",
|
||||
"marked": "^0.8.0",
|
||||
@ -63,8 +63,8 @@
|
||||
"zone.js": "^0.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.803.21",
|
||||
"@angular/cli": "^8.3.21",
|
||||
"@angular-devkit/build-angular": "^0.803.22",
|
||||
"@angular/cli": "^8.3.22",
|
||||
"@angular/compiler-cli": "^8.2.14",
|
||||
"@angular/language-service": "^8.2.14",
|
||||
"@types/chartist": "^0.9.46",
|
||||
@ -72,7 +72,7 @@
|
||||
"@types/jasmine": "~3.5.0",
|
||||
"@types/jasminewd2": "~2.0.8",
|
||||
"@types/marked": "^0.7.2",
|
||||
"@types/node": "^12.12.22",
|
||||
"@types/node": "^13.1.6",
|
||||
"bourbon": "6.0.0",
|
||||
"bourbon-neat": "4.0.0",
|
||||
"codelyzer": "^5.2.1",
|
||||
@ -82,13 +82,13 @@
|
||||
"karma": "^4.4.1",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine": "~3.1.0",
|
||||
"karma-jasmine-html-reporter": "^1.5.1",
|
||||
"nodemon": "^2.0.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"protractor": "~5.4.2",
|
||||
"puppeteer": "^2.0.0",
|
||||
"ts-node": "^8.5.4",
|
||||
"ts-node": "^8.6.1",
|
||||
"tslint": "~5.20.1",
|
||||
"typescript": "^3.5.3"
|
||||
}
|
||||
|
@ -2,60 +2,60 @@
|
||||
$container = $app->getContainer();
|
||||
|
||||
// Inject a Monolog logger into the dependency container
|
||||
$container['logger'] = function($c) {
|
||||
$logger = new Monolog\Logger('API');
|
||||
$fileHandler = new Monolog\Handler\StreamHandler('logs/api.log');
|
||||
$container['logger'] = function() {
|
||||
$logger = new Monolog\Logger('API');
|
||||
$fileHandler = new Monolog\Handler\StreamHandler('logs/api.log');
|
||||
|
||||
$logger->pushHandler($fileHandler);
|
||||
$logger->pushHandler($fileHandler);
|
||||
|
||||
return $logger;
|
||||
return $logger;
|
||||
};
|
||||
|
||||
// Replace notFoundHandler to use an API response
|
||||
$container['notFoundHandler'] = function($c) {
|
||||
return function($request, $response) use ($c) {
|
||||
return $c['response']
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->write('{ message: "Matching API call not found." }');
|
||||
};
|
||||
return function() use ($c) {
|
||||
return $c['response']
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->write('{ message: "Matching API call not found." }');
|
||||
};
|
||||
};
|
||||
|
||||
// Replace the errorHandler to use an API response
|
||||
$container['errorHandler'] = function ($c) {
|
||||
return function ($request, $response, $exception) use ($c) {
|
||||
$c['logger']->addError('Server error', $exception->getTrace());
|
||||
return function ($exception) use ($c) {
|
||||
$c['logger']->addError('Server error', $exception->getTrace());
|
||||
|
||||
return $c['response']->withStatus(500)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->write('{ message: "Internal Server Error", error: "' .
|
||||
$exception->getMessage() . '" }');
|
||||
};
|
||||
return $c['response']->withStatus(500)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->write('{ message: "Internal Server Error", error: "' .
|
||||
$exception->getMessage() . '" }');
|
||||
};
|
||||
};
|
||||
|
||||
$container['phpErrorHandler'] = function ($c) {
|
||||
return function ($request, $response, $exception) use ($c) {
|
||||
$c['logger']->addError('Server error', $exception->getTrace());
|
||||
return function ($exception) use ($c) {
|
||||
$c['logger']->addError('Server error', $exception->getTrace());
|
||||
|
||||
return $c['response']->withStatus(500)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->write('{ message: "Internal Server Error", error: "' .
|
||||
$exception->getMessage() . '" }');
|
||||
};
|
||||
return $c['response']->withStatus(500)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->write('{ message: "Internal Server Error", error: "' .
|
||||
$exception->getMessage() . '" }');
|
||||
};
|
||||
};
|
||||
|
||||
// Routes ending in '/' use route without '/'
|
||||
$app->add(function($request, $response, $next) {
|
||||
$uri = $request->getUri();
|
||||
$path = $uri->getPath();
|
||||
$uri = $request->getUri();
|
||||
$path = $uri->getPath();
|
||||
|
||||
if (strlen($path) > 1 && substr($path, -1) === '/') {
|
||||
$path = substr($path, 0, -1);
|
||||
}
|
||||
if (strlen($path) > 1 && substr($path, -1) === '/') {
|
||||
$path = substr($path, 0, -1);
|
||||
}
|
||||
|
||||
if ($uri->getPath() !== $path) {
|
||||
return $next($request->withUri($uri->withPath($path)), $response);
|
||||
}
|
||||
if ($uri->getPath() !== $path) {
|
||||
return $next($request->withUri($uri->withPath($path)), $response);
|
||||
}
|
||||
|
||||
return $next($request, $response);
|
||||
return $next($request, $response);
|
||||
});
|
||||
|
||||
|
@ -1,23 +1,23 @@
|
||||
{
|
||||
"require": {
|
||||
"monolog/monolog": "^1.18",
|
||||
"gabordemooij/redbean": "^5.1",
|
||||
"slim/slim": "^3.3",
|
||||
"firebase/php-jwt": "^5.0",
|
||||
"phpmailer/phpmailer": "^6.0",
|
||||
"phpunit/phpunit": "^6.0",
|
||||
"myclabs/php-enum": "^1.5"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matthew Ross",
|
||||
"email": "root@matthewross.me",
|
||||
"homepage": "https://matthewross.me",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"classmap": [ "controllers", "helpers" ]
|
||||
"require": {
|
||||
"monolog/monolog": "^2.0",
|
||||
"gabordemooij/redbean": "^5.4",
|
||||
"slim/slim": "^4.3",
|
||||
"firebase/php-jwt": "^5.0",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"myclabs/php-enum": "^1.7"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matthew Ross",
|
||||
"email": "root@matthewross.me",
|
||||
"homepage": "https://matthewross.me",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"classmap": [ "controllers", "helpers" ]
|
||||
}
|
||||
}
|
||||
|
681
src/api/composer.lock
generated
681
src/api/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -3,88 +3,88 @@ use RedBeanPHP\R;
|
||||
|
||||
class Activity extends BaseController {
|
||||
|
||||
public function getActivity($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$activity = [];
|
||||
|
||||
// TODO: More activity types
|
||||
if ($args['type'] === 'task') {
|
||||
if (!$this->checkBoardAccess($this->getBoardId((int)$args['id']),
|
||||
$request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$activity = $this->getTaskActivity((int)$args['id']);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($activity);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function getActivity($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
private function getBoardId($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$column = R::load('column', $task->column_id);
|
||||
$activity = [];
|
||||
|
||||
return $column->board_id;
|
||||
// TODO: More activity types
|
||||
if ($args['type'] === 'task') {
|
||||
if (!$this->checkBoardAccess($this->getBoardId((int)$args['id']),
|
||||
$request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$activity = $this->getTaskActivity((int)$args['id']);
|
||||
}
|
||||
|
||||
private function sortLogs($a, $b) {
|
||||
if ($a->timestamp === $b->timestamp) {
|
||||
return 0; // @codeCoverageIgnore
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($activity);
|
||||
|
||||
return $a->timestamp > $b->timestamp ? -1 : 1;
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function getBoardId($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
return $column->board_id;
|
||||
}
|
||||
|
||||
private function sortLogs($a, $b) {
|
||||
if ($a->timestamp === $b->timestamp) {
|
||||
return 0; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
private function getTaskActivity($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$logs = [];
|
||||
$commentIds = [];
|
||||
$attachmentIds = [];
|
||||
return $a->timestamp > $b->timestamp ? -1 : 1;
|
||||
}
|
||||
|
||||
foreach ($task->ownComment as $comment) {
|
||||
$commentIds[] = (int)$comment->id;
|
||||
}
|
||||
private function getTaskActivity($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$logs = [];
|
||||
$commentIds = [];
|
||||
$attachmentIds = [];
|
||||
|
||||
foreach ($task->ownAttachment as $attachment) {
|
||||
$attachmentIds[] = (int)$attachment->id;
|
||||
}
|
||||
|
||||
$taskActivity = R::find('activity',
|
||||
'item_type="task" AND item_id=?',
|
||||
[$taskId]);
|
||||
$this->addLogItems($logs, $taskActivity);
|
||||
|
||||
$commentActivity =
|
||||
R::find('activity', 'item_type="comment" AND '.
|
||||
'item_id IN(' . R::genSlots($commentIds) . ')',
|
||||
$commentIds);
|
||||
$this->addLogItems($logs, $commentActivity);
|
||||
|
||||
$attachmentActivity =
|
||||
R::find('activity', 'item_type="attachment" AND '.
|
||||
'item_id IN(' . R::genSlots($attachmentIds) . ')',
|
||||
$attachmentIds);
|
||||
$this->addLogItems($logs, $attachmentActivity);
|
||||
|
||||
usort($logs, array("Activity", "sortLogs"));
|
||||
|
||||
return $logs;
|
||||
foreach ($task->ownComment as $comment) {
|
||||
$commentIds[] = (int)$comment->id;
|
||||
}
|
||||
|
||||
private function addLogItems(&$logs, $items) {
|
||||
foreach ($items as $logItem) {
|
||||
$logs[] = (object)array('text'=>$logItem->log_text,
|
||||
'timestamp'=>$logItem->timestamp);
|
||||
}
|
||||
foreach ($task->ownAttachment as $attachment) {
|
||||
$attachmentIds[] = (int)$attachment->id;
|
||||
}
|
||||
|
||||
$taskActivity = R::find('activity',
|
||||
'item_type="task" AND item_id=?',
|
||||
[$taskId]);
|
||||
$this->addLogItems($logs, $taskActivity);
|
||||
|
||||
$commentActivity =
|
||||
R::find('activity', 'item_type="comment" AND '.
|
||||
'item_id IN(' . R::genSlots($commentIds) . ')',
|
||||
$commentIds);
|
||||
$this->addLogItems($logs, $commentActivity);
|
||||
|
||||
$attachmentActivity =
|
||||
R::find('activity', 'item_type="attachment" AND '.
|
||||
'item_id IN(' . R::genSlots($attachmentIds) . ')',
|
||||
$attachmentIds);
|
||||
$this->addLogItems($logs, $attachmentActivity);
|
||||
|
||||
usort($logs, array("Activity", "sortLogs"));
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
private function addLogItems(&$logs, $items) {
|
||||
foreach ($items as $logItem) {
|
||||
$logs[] = (object)array('text'=>$logItem->log_text,
|
||||
'timestamp'=>$logItem->timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,131 +3,131 @@ use RedBeanPHP\R;
|
||||
|
||||
class Attachments extends BaseController {
|
||||
|
||||
public function getAttachment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
public function getAttachment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$attachment = R::load('attachment', (int)$args['id']);
|
||||
$attachment = R::load('attachment', (int)$args['id']);
|
||||
|
||||
if ($attachment->id === 0) {
|
||||
$this->logger->addError('Attempt to load attachment ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No attachment found for ID ' .
|
||||
$args['id'] . '.');
|
||||
if ($attachment->id === 0) {
|
||||
$this->logger->addError('Attempt to load attachment ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No attachment found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($this->getBoardId($attachment->task_id),
|
||||
$request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
if (!$this->checkBoardAccess($this->getBoardId($attachment->task_id),
|
||||
$request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($attachment);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($attachment);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addAttachment($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$attachment = R::dispense('attachment');
|
||||
if (!BeanLoader::LoadAttachment($attachment, $request->getBody())) {
|
||||
$attachment->task_id = 0;
|
||||
}
|
||||
|
||||
$task = R::load('task', $attachment->task_id);
|
||||
|
||||
if ($task->id === 0) {
|
||||
$this->logger->addError('Add Attachment: ', [$attachment]);
|
||||
$this->apiJson->addAlert('error', 'Error adding attachment. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($this->getBoardId($task->id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($attachment);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added attachment.', '', json_encode($attachment),
|
||||
'attachment', $attachment->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Attachment added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeAttachment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$attachment = R::load('attachment', $id);
|
||||
|
||||
// If User level, only the user that created the attachment
|
||||
// may delete it. If higher level, delete is allowed.
|
||||
if ((int)$actor->security_level === SecurityLevel::USER) {
|
||||
if ($actor->id !== $attachment->user_id) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'You do not have sufficient permissions ' .
|
||||
'to remove this attachment.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
if ((int)$attachment->id !== $id) {
|
||||
$this->logger->addError('Remove Attachment: ', [$attachment]);
|
||||
$this->apiJson->addAlert('error', 'Error removing attachment. ' .
|
||||
'No attachment found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addAttachment($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$attachment = R::dispense('attachment');
|
||||
if (!BeanLoader::LoadAttachment($attachment, $request->getBody())) {
|
||||
$attachment->task_id = 0;
|
||||
}
|
||||
|
||||
$task = R::load('task', $attachment->task_id);
|
||||
|
||||
if ($task->id === 0) {
|
||||
$this->logger->addError('Add Attachment: ', [$attachment]);
|
||||
$this->apiJson->addAlert('error', 'Error adding attachment. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($this->getBoardId($task->id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($attachment);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added attachment.', '', json_encode($attachment),
|
||||
'attachment', $attachment->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Attachment added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if (!$this->checkBoardAccess($this->getBoardId($attachment->task_id),
|
||||
$request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
public function removeAttachment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$before = $attachment;
|
||||
$attachment->delete();
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username .' removed attachment ' . $before->name,
|
||||
json_encode($before), '', 'attachment', $id);
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$attachment = R::load('attachment', $id);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Attachment ' . $before->name . ' removed.');
|
||||
|
||||
// If User level, only the user that created the attachment
|
||||
// may delete it. If higher level, delete is allowed.
|
||||
if ((int)$actor->security_level === SecurityLevel::USER) {
|
||||
if ($actor->id !== $attachment->user_id) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'You do not have sufficient permissions ' .
|
||||
'to remove this attachment.');
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
private function getBoardId($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
if ((int)$attachment->id !== $id) {
|
||||
$this->logger->addError('Remove Attachment: ', [$attachment]);
|
||||
$this->apiJson->addAlert('error', 'Error removing attachment. ' .
|
||||
'No attachment found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($this->getBoardId($attachment->task_id),
|
||||
$request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $attachment;
|
||||
$attachment->delete();
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username .' removed attachment ' . $before->name,
|
||||
json_encode($before), '', 'attachment', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Attachment ' . $before->name . ' removed.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function getBoardId($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
return $column->board_id;
|
||||
}
|
||||
return $column->board_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,292 +4,292 @@ use Firebase\JWT\JWT;
|
||||
|
||||
class Auth extends BaseController {
|
||||
|
||||
public static function HasBoardAccess($request, $boardId, $userId = null) {
|
||||
$hasAccess = false;
|
||||
public static function HasBoardAccess($request, $boardId, $userId = null) {
|
||||
$hasAccess = false;
|
||||
|
||||
if ($userId === null) {
|
||||
$userId = self::GetUserId($request);
|
||||
}
|
||||
|
||||
$user = R::load('user', $userId);
|
||||
if ((int)$user->security_level === SecurityLevel::ADMIN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$board = R::load('board', $boardId);
|
||||
|
||||
foreach ($board->sharedUserList as $check) {
|
||||
if ((int)$check->id === $userId) {
|
||||
$hasAccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $hasAccess;
|
||||
if ($userId === null) {
|
||||
$userId = self::GetUserId($request);
|
||||
}
|
||||
|
||||
public static function CreateInitialAdmin() {
|
||||
$admin = R::load('user', 1);
|
||||
|
||||
// Don't create more than one admin
|
||||
if ($admin->id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$admin->security_level = SecurityLevel::ADMIN()->getValue();
|
||||
$admin->username = 'admin';
|
||||
$admin->password_hash = password_hash('admin', PASSWORD_BCRYPT);
|
||||
$admin->email = '';
|
||||
$admin->default_board_id = 0;
|
||||
$admin->user_option_id = 0;
|
||||
$admin->last_login = 0;
|
||||
$admin->active_token = '';
|
||||
|
||||
$opts = R::dispense('useroption');
|
||||
$opts->new_tasks_at_bottom = true;
|
||||
$opts->show_animations = true;
|
||||
$opts->show_assignee = true;
|
||||
$opts->multiple_tasks_per_row = false;
|
||||
$opts->language = 'en';
|
||||
|
||||
R::store($opts);
|
||||
$admin->user_option_id = $opts->id;
|
||||
R::store($admin);
|
||||
$user = R::load('user', $userId);
|
||||
if ((int)$user->security_level === SecurityLevel::ADMIN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function CreateJwtSigningKey() {
|
||||
$key = R::load('jwt', 1);
|
||||
$board = R::load('board', $boardId);
|
||||
|
||||
// Don't create more than one secret key
|
||||
if ($key->id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate a JWT signing key by hashing the current time.
|
||||
$key->secret = hash('sha512', strval(time()));
|
||||
|
||||
R::store($key);
|
||||
foreach ($board->sharedUserList as $check) {
|
||||
if ((int)$check->id === $userId) {
|
||||
$hasAccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static function ValidateToken($request, $response) {
|
||||
if (!$request->hasHeader('Authorization')) {
|
||||
return $response->withStatus(400);
|
||||
}
|
||||
return $hasAccess;
|
||||
}
|
||||
|
||||
$jwt = $request->getHeader('Authorization')[0];
|
||||
$payload = self::getJwtPayload($jwt);
|
||||
public static function CreateInitialAdmin() {
|
||||
$admin = R::load('user', 1);
|
||||
|
||||
if ($payload === null) {
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
|
||||
$user = R::load('user', $payload->uid);
|
||||
|
||||
if ($user->active_token !== $jwt) {
|
||||
$user->active_token = '';
|
||||
R::store($user);
|
||||
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
|
||||
$response->getBody()->write($jwt);
|
||||
|
||||
return $response;
|
||||
// Don't create more than one admin
|
||||
if ($admin->id) {
|
||||
return;
|
||||
}
|
||||
|
||||
public static function GetUserId($request) {
|
||||
$uid = -1;
|
||||
$admin->security_level = SecurityLevel::ADMIN()->getValue();
|
||||
$admin->username = 'admin';
|
||||
$admin->password_hash = password_hash('admin', PASSWORD_BCRYPT);
|
||||
$admin->email = '';
|
||||
$admin->default_board_id = 0;
|
||||
$admin->user_option_id = 0;
|
||||
$admin->last_login = 0;
|
||||
$admin->active_token = '';
|
||||
|
||||
try {
|
||||
$jwt = $request->getHeader('Authorization')[0];
|
||||
} catch (Exception $ex) {
|
||||
return $uid;
|
||||
}
|
||||
$opts = R::dispense('useroption');
|
||||
$opts->new_tasks_at_bottom = true;
|
||||
$opts->show_animations = true;
|
||||
$opts->show_assignee = true;
|
||||
$opts->multiple_tasks_per_row = false;
|
||||
$opts->language = 'en';
|
||||
|
||||
$payload = self::getJwtPayload($jwt);
|
||||
R::store($opts);
|
||||
$admin->user_option_id = $opts->id;
|
||||
R::store($admin);
|
||||
}
|
||||
|
||||
if ($payload !== null) {
|
||||
$uid = $payload->uid;
|
||||
}
|
||||
public static function CreateJwtSigningKey() {
|
||||
$key = R::load('jwt', 1);
|
||||
|
||||
return $uid;
|
||||
// Don't create more than one secret key
|
||||
if ($key->id) {
|
||||
return;
|
||||
}
|
||||
|
||||
public function login($request, $response) {
|
||||
$data = json_decode($request->getBody());
|
||||
$user = R::findOne('user', 'username = ?', [$data->username]);
|
||||
// Generate a JWT signing key by hashing the current time.
|
||||
$key->secret = hash('sha512', strval(time()));
|
||||
|
||||
if ($user === null) {
|
||||
$this->logger->addError('Login: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Invalid username or password.');
|
||||
R::store($key);
|
||||
}
|
||||
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
if (!password_verify($data->password, $user->password_hash)) {
|
||||
$this->logger->addError('Login: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Invalid username or password.');
|
||||
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
$jwt = self::createJwt($user->id, ($data->remember ? 200 : 1));
|
||||
$user = R::load('user', $user->id);
|
||||
|
||||
if ($user->username === 'admin' && (int)$user->last_login === 0) {
|
||||
$this->apiJson->addAlert('warn',
|
||||
'This is your first login, go to Settings ' .
|
||||
'to change your password.');
|
||||
$this->apiJson->addAlert('success',
|
||||
'Go to Settings to create your first board.');
|
||||
}
|
||||
|
||||
$user->active_token = $jwt;
|
||||
$user->last_login = time();
|
||||
R::store($user);
|
||||
|
||||
$this->dbLogger->logChange($user->id, $user->username . ' logged in',
|
||||
null, null, 'user', $user->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($jwt);
|
||||
$this->apiJson->addData($this->sanitizeUser($user));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public static function ValidateToken($request, $response) {
|
||||
if (!$request->hasHeader('Authorization')) {
|
||||
return $response->withStatus(400);
|
||||
}
|
||||
|
||||
public function logout($request, $response) {
|
||||
if (!$request->hasHeader('Authorization')) {
|
||||
return $this->jsonResponse($response, 400);
|
||||
}
|
||||
$jwt = $request->getHeader('Authorization')[0];
|
||||
$payload = self::getJwtPayload($jwt);
|
||||
|
||||
$jwt = $request->getHeader('Authorization')[0];
|
||||
$payload = self::getJwtPayload($jwt);
|
||||
|
||||
if ($payload === null) {
|
||||
$this->apiJson->addAlert('error', 'Invalid access token.');
|
||||
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
$user = R::load('user', $payload->uid);
|
||||
|
||||
if ($user->id) {
|
||||
$user->active_token = '';
|
||||
R::store($user);
|
||||
}
|
||||
|
||||
$this->dbLogger->logChange($user->id, $user->username . ' logged out',
|
||||
null, null, 'user', $user->id);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'You have been logged out.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if ($payload === null) {
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
|
||||
public function authenticate($request, $response) {
|
||||
$response = self::ValidateToken($request, $response);
|
||||
$status = $response->getStatusCode();
|
||||
$user = R::load('user', $payload->uid);
|
||||
|
||||
if ($status !== 200) {
|
||||
if ($status === 400) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'Authorization header missing.');
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
if ($user->active_token !== $jwt) {
|
||||
$user->active_token = '';
|
||||
R::store($user);
|
||||
|
||||
$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);
|
||||
$opts = R::load('useroption', $user->user_option_id);
|
||||
$collapsed = R::find('collapsed', ' user_id = ? ', [ $user->id ]);
|
||||
|
||||
$user->collapsed = [];
|
||||
foreach ($collapsed as $collapse) {
|
||||
$user->collapsed[] = $collapse->column_id;
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($jwt);
|
||||
$this->apiJson->addData($this->sanitizeUser($user));
|
||||
$this->apiJson->addData($opts);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
|
||||
public function refreshToken($request, $response) {
|
||||
$response = self::ValidateToken($request, $response);
|
||||
$status = $response->getStatusCode();
|
||||
$response->getBody()->write($jwt);
|
||||
|
||||
if ($status !== 200) {
|
||||
if ($status === 400) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'Authorization header missing.');
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
$this->apiJson->addAlert('error', 'Invalid API token.');
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
public static function GetUserId($request) {
|
||||
$uid = -1;
|
||||
|
||||
$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);
|
||||
try {
|
||||
$jwt = $request->getHeader('Authorization')[0];
|
||||
} catch (Exception $ex) {
|
||||
return $uid;
|
||||
}
|
||||
|
||||
private function sanitizeUser($user) {
|
||||
unset($user->password_hash);
|
||||
unset($user->active_token);
|
||||
$payload = self::getJwtPayload($jwt);
|
||||
|
||||
return $user;
|
||||
if ($payload !== null) {
|
||||
$uid = $payload->uid;
|
||||
}
|
||||
|
||||
private static function getJwtPayload($jwt) {
|
||||
try {
|
||||
$payload = JWT::decode($jwt, self::getJwtKey(), ['HS256']);
|
||||
} catch (Exception $ex) {
|
||||
return null;
|
||||
}
|
||||
return $uid;
|
||||
}
|
||||
|
||||
return $payload;
|
||||
public function login($request, $response) {
|
||||
$data = json_decode($request->getBody());
|
||||
$user = R::findOne('user', 'username = ?', [$data->username]);
|
||||
|
||||
if ($user === null) {
|
||||
$this->logger->addError('Login: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Invalid username or password.');
|
||||
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
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.
|
||||
if (!password_verify($data->password, $user->password_hash)) {
|
||||
$this->logger->addError('Login: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Invalid username or password.');
|
||||
|
||||
return JWT::encode(array(
|
||||
'exp' => time() + (60 * 30) * $mult, // 30 minutes * $mult
|
||||
'uid' => (int)$userId,
|
||||
'mul' => $mult
|
||||
), Auth::getJwtKey());
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
private static function getJwtKey() {
|
||||
self::CreateJwtSigningKey();
|
||||
$key = R::load('jwt', 1);
|
||||
$jwt = self::createJwt($user->id, ($data->remember ? 200 : 1));
|
||||
$user = R::load('user', $user->id);
|
||||
|
||||
return $key->secret;
|
||||
if ($user->username === 'admin' && (int)$user->last_login === 0) {
|
||||
$this->apiJson->addAlert('warn',
|
||||
'This is your first login, go to Settings ' .
|
||||
'to change your password.');
|
||||
$this->apiJson->addAlert('success',
|
||||
'Go to Settings to create your first board.');
|
||||
}
|
||||
|
||||
$user->active_token = $jwt;
|
||||
$user->last_login = time();
|
||||
R::store($user);
|
||||
|
||||
$this->dbLogger->logChange($user->id, $user->username . ' logged in',
|
||||
null, null, 'user', $user->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($jwt);
|
||||
$this->apiJson->addData($this->sanitizeUser($user));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function logout($request, $response) {
|
||||
if (!$request->hasHeader('Authorization')) {
|
||||
return $this->jsonResponse($response, 400);
|
||||
}
|
||||
|
||||
$jwt = $request->getHeader('Authorization')[0];
|
||||
$payload = self::getJwtPayload($jwt);
|
||||
|
||||
if ($payload === null) {
|
||||
$this->apiJson->addAlert('error', 'Invalid access token.');
|
||||
|
||||
return $this->jsonResponse($response, 401);
|
||||
}
|
||||
|
||||
$user = R::load('user', $payload->uid);
|
||||
|
||||
if ($user->id) {
|
||||
$user->active_token = '';
|
||||
R::store($user);
|
||||
}
|
||||
|
||||
$this->dbLogger->logChange($user->id, $user->username . ' logged out',
|
||||
null, null, 'user', $user->id);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'You have been logged out.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function authenticate($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);
|
||||
$opts = R::load('useroption', $user->user_option_id);
|
||||
$collapsed = R::find('collapsed', ' user_id = ? ', [ $user->id ]);
|
||||
|
||||
$user->collapsed = [];
|
||||
foreach ($collapsed as $collapse) {
|
||||
$user->collapsed[] = $collapse->column_id;
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($jwt);
|
||||
$this->apiJson->addData($this->sanitizeUser($user));
|
||||
$this->apiJson->addData($opts);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private function sanitizeUser($user) {
|
||||
unset($user->password_hash);
|
||||
unset($user->active_token);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private static function getJwtPayload($jwt) {
|
||||
try {
|
||||
$payload = JWT::decode($jwt, self::getJwtKey(), ['HS256']);
|
||||
} catch (Exception $ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
return JWT::encode(array(
|
||||
'exp' => time() + (60 * 30) * $mult, // 30 minutes * $mult
|
||||
'uid' => (int)$userId,
|
||||
'mul' => $mult
|
||||
), Auth::getJwtKey());
|
||||
}
|
||||
|
||||
private static function getJwtKey() {
|
||||
self::CreateJwtSigningKey();
|
||||
$key = R::load('jwt', 1);
|
||||
|
||||
return $key->secret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,124 +3,124 @@ use RedBeanPHP\R;
|
||||
|
||||
class AutoActions extends BaseController {
|
||||
|
||||
public function getAllActions($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$autoActions = $this->getAll($request);
|
||||
|
||||
if (!count($autoActions)) {
|
||||
$this->apiJson->addAlert('info',
|
||||
'No automatic actions in database.');
|
||||
$this->apiJson->addData([]);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($autoActions);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function getAllActions($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
public function addAction($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$autoActions = $this->getAll($request);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
if (!BeanLoader::LoadAutoAction($action, $request->getBody())) {
|
||||
$action->board_id = 0;
|
||||
}
|
||||
if (!count($autoActions)) {
|
||||
$this->apiJson->addAlert('info',
|
||||
'No automatic actions in database.');
|
||||
$this->apiJson->addData([]);
|
||||
|
||||
$board = R::load('board', $action->board_id);
|
||||
|
||||
if ($board->id === 0) {
|
||||
$this->logger->addError('Add Action: ', [$action]);
|
||||
$this->apiJson->addAlert('error',
|
||||
'Error adding automatic action. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($action->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($action);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added automatic action.',
|
||||
'', json_encode($action), 'action', $action->id);
|
||||
|
||||
$actions = $this->getAll($request);
|
||||
|
||||
$this->apiJson->setSuccess($actions);
|
||||
$this->apiJson->addData($actions);
|
||||
$this->apiJson->addAlert('success', 'Automatic action added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeAction($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($autoActions);
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$action = R::load('autoaction', $id);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if ((int)$action->id !== $id) {
|
||||
$this->logger->addError('Remove Action: ', [$action]);
|
||||
$this->apiJson->addAlert('error', 'Error removing action. ' .
|
||||
'No action found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($action->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $action;
|
||||
R::trash($action);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username .' removed action ' . $before['id'] . '.',
|
||||
json_encode($before), '', 'action', $id);
|
||||
|
||||
$actions = $this->getAll($request);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($actions);
|
||||
$this->apiJson->addAlert('success', 'Automatic action removed.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function addAction($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
private function getAll($request) {
|
||||
$autoActions = R::findAll('autoaction');
|
||||
$data = [];
|
||||
|
||||
foreach ($autoActions as $action) {
|
||||
if (Auth::HasBoardAccess($request, $action->board_id)) {
|
||||
$data[] = $action;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
$action = R::dispense('autoaction');
|
||||
if (!BeanLoader::LoadAutoAction($action, $request->getBody())) {
|
||||
$action->board_id = 0;
|
||||
}
|
||||
|
||||
$board = R::load('board', $action->board_id);
|
||||
|
||||
if ($board->id === 0) {
|
||||
$this->logger->addError('Add Action: ', [$action]);
|
||||
$this->apiJson->addAlert('error',
|
||||
'Error adding automatic action. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($action->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($action);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added automatic action.',
|
||||
'', json_encode($action), 'action', $action->id);
|
||||
|
||||
$actions = $this->getAll($request);
|
||||
|
||||
$this->apiJson->setSuccess($actions);
|
||||
$this->apiJson->addData($actions);
|
||||
$this->apiJson->addAlert('success', 'Automatic action added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeAction($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$action = R::load('autoaction', $id);
|
||||
|
||||
if ((int)$action->id !== $id) {
|
||||
$this->logger->addError('Remove Action: ', [$action]);
|
||||
$this->apiJson->addAlert('error', 'Error removing action. ' .
|
||||
'No action found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($action->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $action;
|
||||
R::trash($action);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username .' removed action ' . $before['id'] . '.',
|
||||
json_encode($before), '', 'action', $id);
|
||||
|
||||
$actions = $this->getAll($request);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($actions);
|
||||
$this->apiJson->addAlert('success', 'Automatic action removed.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function getAll($request) {
|
||||
$autoActions = R::findAll('autoaction');
|
||||
$data = [];
|
||||
|
||||
foreach ($autoActions as $action) {
|
||||
if (Auth::HasBoardAccess($request, $action->board_id)) {
|
||||
$data[] = $action;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,57 +2,57 @@
|
||||
use RedBeanPHP\R;
|
||||
|
||||
abstract class BaseController {
|
||||
protected $apiJson;
|
||||
protected $logger;
|
||||
protected $dbLogger;
|
||||
protected $container;
|
||||
protected $apiJson;
|
||||
protected $logger;
|
||||
protected $dbLogger;
|
||||
protected $container;
|
||||
|
||||
public function __construct($container) {
|
||||
$this->apiJson = new ApiJson();
|
||||
$this->logger = $container->get('logger');
|
||||
$this->dbLogger = new DbLogger();
|
||||
$this->container = $container;
|
||||
public function __construct($container) {
|
||||
$this->apiJson = new ApiJson();
|
||||
$this->logger = $container->get('logger');
|
||||
$this->dbLogger = new DbLogger();
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function jsonResponse($response, $status = 200) {
|
||||
return $response->withStatus($status)->withJson($this->apiJson);
|
||||
}
|
||||
|
||||
public function checkBoardAccess($boardId, $request) {
|
||||
if (!Auth::HasBoardAccess($request, $boardId)) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function jsonResponse($response, $status = 200) {
|
||||
return $response->withStatus($status)->withJson($this->apiJson);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkBoardAccess($boardId, $request) {
|
||||
if (!Auth::HasBoardAccess($request, $boardId)) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function secureRoute($request, $response, $securityLevel) {
|
||||
$response = Auth::ValidateToken($request, $response);
|
||||
$status = $response->getStatusCode();
|
||||
|
||||
if ($status !== 200) {
|
||||
if ($status === 400) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'Authorization header missing.');
|
||||
return $status;
|
||||
}
|
||||
|
||||
$this->apiJson->addAlert('error', 'Invalid API token.');
|
||||
return $status;
|
||||
}
|
||||
|
||||
$user = R::load('user', Auth::GetUserId($request));
|
||||
if ((int)$user->security_level > $securityLevel) {
|
||||
$this->apiJson->addAlert('error', 'Insufficient privileges.');
|
||||
|
||||
return 403;
|
||||
}
|
||||
|
||||
$this->apiJson->addData((string) $response->getBody());
|
||||
public function secureRoute($request, $response, $securityLevel) {
|
||||
$response = Auth::ValidateToken($request, $response);
|
||||
$status = $response->getStatusCode();
|
||||
|
||||
if ($status !== 200) {
|
||||
if ($status === 400) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'Authorization header missing.');
|
||||
return $status;
|
||||
}
|
||||
|
||||
$this->apiJson->addAlert('error', 'Invalid API token.');
|
||||
return $status;
|
||||
}
|
||||
|
||||
$user = R::load('user', Auth::GetUserId($request));
|
||||
if ((int)$user->security_level > $securityLevel) {
|
||||
$this->apiJson->addAlert('error', 'Insufficient privileges.');
|
||||
|
||||
return 403;
|
||||
}
|
||||
|
||||
$this->apiJson->addData((string) $response->getBody());
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,232 +3,224 @@ use RedBeanPHP\R;
|
||||
|
||||
class Boards extends BaseController {
|
||||
|
||||
public function getAllBoards($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$boards = $this->loadAllBoards($request);
|
||||
|
||||
if (!count($boards)) {
|
||||
$this->apiJson->addAlert('info', 'No boards in database.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($boards);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function getAllBoards($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
public function getBoard($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$boards = $this->loadAllBoards($request);
|
||||
|
||||
$board = R::load('board', (int)$args['id']);
|
||||
if (!count($boards)) {
|
||||
$this->apiJson->addAlert('info', 'No boards in database.');
|
||||
|
||||
if ($board->id === 0) {
|
||||
$this->logger->addError('Attempt to load board ' . $args['id'] .
|
||||
' failed.');
|
||||
$this->apiJson->addAlert('error', 'No board found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($board->id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$this->cleanBoard($board);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addBoard($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($boards);
|
||||
|
||||
$board = R::dispense('board');
|
||||
if (!BeanLoader::LoadBoard($board, $request->getBody())) {
|
||||
$board->id = -1;
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$this->includeAdmins($board);
|
||||
|
||||
if ($board->id === -1) {
|
||||
$this->logger->addError('Add Board: ', [$board]);
|
||||
$this->apiJson->addAlert('error', 'Error adding board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
R::store($board);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added board ' . $board->name . '.',
|
||||
'', json_encode($board), 'board', $board->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Board ' . $board->name . ' added.');
|
||||
$this->apiJson->addData($this->loadAllBoards($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function getBoard($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
public function updateBoard($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$board = R::load('board', (int)$args['id']);
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
if ($board->id === 0) {
|
||||
$this->logger->addError('Attempt to load board ' . $args['id'] .
|
||||
' failed.');
|
||||
$this->apiJson->addAlert('error', 'No board found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
if (!property_exists($args, 'id')) {
|
||||
$this->logger->addError('Update Board: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$board = R::load('board', (int)$args['id']);
|
||||
|
||||
if (!$this->checkBoardAccess($board->id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
if (!property_exists($data, 'id')) {
|
||||
$this->logger->addError('Update Board: ', [$board, $data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$update = R::load('board', (int)$args['id']);
|
||||
$update->id = BeanLoader::LoadBoard($update, $request->getBody())
|
||||
? $board->id : 0;
|
||||
|
||||
if ($update->id === 0 || ($board->id !== $update->id)) {
|
||||
$this->logger->addError('Update Board: ', [$board, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$this->includeAdmins($update);
|
||||
R::store($update);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated board ' . $update->name,
|
||||
json_encode(R::exportAll($board)),
|
||||
json_encode(R::exportAll($update)), 'board', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Board ' . $update->name . ' updated.');
|
||||
$this->apiJson->addData($this->loadAllBoards($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeBoard($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$board = R::load('board', $id);
|
||||
|
||||
if ((int)$board->id !== $id) {
|
||||
$this->logger->addError('Remove Board: ', [$board]);
|
||||
$this->apiJson->addAlert('error', 'Error removing board. ' .
|
||||
'No board found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$before = $board;
|
||||
R::trash($board);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed board ' . $before->name,
|
||||
json_encode($before), '', 'board', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Board ' . $before->name . ' removed.');
|
||||
$this->apiJson->addData($this->loadAllBoards($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if (!$this->checkBoardAccess($board->id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
private function includeAdmins($board) {
|
||||
$admins = R::findAll('user', ' WHERE security_level = 1 ');
|
||||
$this->cleanBoard($board);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
foreach ($admins as $admin) {
|
||||
if (!in_array($admin, $board->sharedUserList)) {
|
||||
$board->sharedUserList[] = $admin;
|
||||
}
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addBoard($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
private function loadAllBoards($request) {
|
||||
$boards = [];
|
||||
$boardBeans = R::findAll('board');
|
||||
|
||||
if (count($boardBeans)) {
|
||||
foreach ($boardBeans as $bean) {
|
||||
if (Auth::HasBoardAccess($request, $bean->id)) {
|
||||
$this->cleanBoard($bean);
|
||||
$boards[] = $bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return R::exportAll($boards);
|
||||
$board = R::dispense('board');
|
||||
if (!BeanLoader::LoadBoard($board, $request->getBody())) {
|
||||
$board->id = -1;
|
||||
}
|
||||
|
||||
private function cleanBoard(&$board) {
|
||||
foreach ($board->sharedUserList as $user) {
|
||||
$user = $this->cleanUser($user);
|
||||
}
|
||||
$this->includeAdmins($board);
|
||||
|
||||
foreach ($board->xownColumnList as $column) {
|
||||
foreach ($column->xownTaskList as $task) {
|
||||
foreach ($task->sharedUserList as $user) {
|
||||
$user = $this->cleanUser($user);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($board->id === -1) {
|
||||
$this->logger->addError('Add Board: ', [$board]);
|
||||
$this->apiJson->addAlert('error', 'Error adding board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function cleanUser($user) {
|
||||
unset($user->password_hash);
|
||||
unset($user->active_token);
|
||||
R::store($board);
|
||||
|
||||
return $user;
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added board ' . $board->name . '.',
|
||||
'', json_encode($board), 'board', $board->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Board ' . $board->name . ' added.');
|
||||
$this->apiJson->addData($this->loadAllBoards($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateBoard($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
|
||||
if (is_null($args) || !array_key_exists('id', $args)) {
|
||||
$this->logger->addError('Update Board: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$board = R::load('board', (int)$args['id']);
|
||||
|
||||
if (!$this->checkBoardAccess($board->id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$update = R::load('board', (int)$args['id']);
|
||||
$update->id = BeanLoader::LoadBoard($update, $request->getBody())
|
||||
? $board->id : 0;
|
||||
|
||||
if ($update->id === 0 || ($board->id !== $update->id)) {
|
||||
$this->logger->addError('Update Board: ', [$board, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating board. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$this->includeAdmins($update);
|
||||
R::store($update);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated board ' . $update->name,
|
||||
json_encode(R::exportAll($board)),
|
||||
json_encode(R::exportAll($update)), 'board', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Board ' . $update->name . ' updated.');
|
||||
$this->apiJson->addData($this->loadAllBoards($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeBoard($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$board = R::load('board', $id);
|
||||
|
||||
if ((int)$board->id !== $id) {
|
||||
$this->logger->addError('Remove Board: ', [$board]);
|
||||
$this->apiJson->addAlert('error', 'Error removing board. ' .
|
||||
'No board found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$before = $board;
|
||||
R::trash($board);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed board ' . $before->name,
|
||||
json_encode($before), '', 'board', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Board ' . $before->name . ' removed.');
|
||||
$this->apiJson->addData($this->loadAllBoards($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function includeAdmins($board) {
|
||||
$admins = R::findAll('user', ' WHERE security_level = 1 ');
|
||||
|
||||
foreach ($admins as $admin) {
|
||||
if (!in_array($admin, $board->sharedUserList)) {
|
||||
$board->sharedUserList[] = $admin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function loadAllBoards($request) {
|
||||
$boards = [];
|
||||
$boardBeans = R::findAll('board');
|
||||
|
||||
if (count($boardBeans)) {
|
||||
foreach ($boardBeans as $bean) {
|
||||
if (Auth::HasBoardAccess($request, $bean->id)) {
|
||||
$this->cleanBoard($bean);
|
||||
$boards[] = $bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return R::exportAll($boards);
|
||||
}
|
||||
|
||||
private function cleanBoard(&$board) {
|
||||
foreach ($board->sharedUserList as $user) {
|
||||
$user = $this->cleanUser($user);
|
||||
}
|
||||
|
||||
foreach ($board->xownColumnList as $column) {
|
||||
foreach ($column->xownTaskList as $task) {
|
||||
foreach ($task->sharedUserList as $user) {
|
||||
$user = $this->cleanUser($user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanUser($user) {
|
||||
unset($user->password_hash);
|
||||
unset($user->active_token);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,151 +3,160 @@ use RedBeanPHP\R;
|
||||
|
||||
class Columns extends BaseController {
|
||||
|
||||
public function getColumn($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$column = R::load('column', (int)$args['id']);
|
||||
|
||||
if ((int)$column->id === 0) {
|
||||
$this->logger->addError('Attempt to load column ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No column found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData(R::exportAll($column));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function getColumn($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
public function addColumn($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$column = R::load('column', (int)$args['id']);
|
||||
|
||||
$column = R::dispense('column');
|
||||
if (!BeanLoader::LoadColumn($column, $request->getBody())) {
|
||||
$column->board_id = 0;
|
||||
}
|
||||
if ((int)$column->id === 0) {
|
||||
$this->logger->addError('Attempt to load column ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No column found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
$board = R::load('board', $column->board_id);
|
||||
|
||||
if ((int)$board->id === 0) {
|
||||
$this->logger->addError('Add Column: ', [$column]);
|
||||
$this->apiJson->addAlert('error', 'Error adding column. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($column);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added column ' . $column->name . '.',
|
||||
'', json_encode($column), 'column', $column->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Column ' .
|
||||
$column->name . ' added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateColumn($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$column = R::load('column', (int)$args['id']);
|
||||
|
||||
$update = R::dispense('column');
|
||||
$update->id = BeanLoader::LoadColumn($update, $request->getBody())
|
||||
? $column->id
|
||||
: 0;
|
||||
|
||||
if ($column->id === 0 || (int)$column->id !== (int)$update->id) {
|
||||
$this->logger->addError('Update Column: ', [$column, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating column ' .
|
||||
$update->name . '. Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($update);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated column ' . $update->name,
|
||||
json_encode($column), json_encode($update),
|
||||
'column', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Column ' .
|
||||
$update->name . ' updated.');
|
||||
$this->apiJson->addData(R::exportAll($update));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
public function removeColumn($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData(R::exportAll($column));
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$column = R::load('column', $id);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if ((int)$column->id !== $id) {
|
||||
$this->logger->addError('Remove Column: ', [$column]);
|
||||
$this->apiJson->addAlert('error', 'Error removing column. ' .
|
||||
'No column found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $column;
|
||||
R::trash($column);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed column ' . $before->name,
|
||||
json_encode($before), '', 'column', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Column ' . $before->name . ' removed.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function addColumn($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$column = R::dispense('column');
|
||||
if (!BeanLoader::LoadColumn($column, $request->getBody())) {
|
||||
$column->board_id = 0;
|
||||
}
|
||||
|
||||
$board = R::load('board', $column->board_id);
|
||||
|
||||
if ((int)$board->id === 0) {
|
||||
$this->logger->addError('Add Column: ', [$column]);
|
||||
$this->apiJson->addAlert('error', 'Error adding column. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($column);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added column ' . $column->name . '.',
|
||||
'', json_encode($column), 'column', $column->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Column ' .
|
||||
$column->name . ' added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateColumn($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
|
||||
if (is_null($args) || !array_key_exists('id', $args)) {
|
||||
$this->logger->addError('Update Task: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating task. Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$column = R::load('column', (int)$args['id']);
|
||||
|
||||
$update = R::dispense('column');
|
||||
$update->id = BeanLoader::LoadColumn($update, $request->getBody())
|
||||
? $column->id
|
||||
: 0;
|
||||
|
||||
if ($column->id === 0 || (int)$column->id !== (int)$update->id) {
|
||||
$this->logger->addError('Update Column: ', [$column, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating column ' .
|
||||
$update->name . '. Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($update);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated column ' . $update->name,
|
||||
json_encode($column), json_encode($update),
|
||||
'column', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Column ' .
|
||||
$update->name . ' updated.');
|
||||
$this->apiJson->addData(R::exportAll($update));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeColumn($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::BOARD_ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$column = R::load('column', $id);
|
||||
|
||||
if ((int)$column->id !== $id) {
|
||||
$this->logger->addError('Remove Column: ', [$column]);
|
||||
$this->apiJson->addAlert('error', 'Error removing column. ' .
|
||||
'No column found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $column;
|
||||
R::trash($column);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed column ' . $before->name,
|
||||
json_encode($before), '', 'column', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Column ' . $before->name . ' removed.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,190 +3,199 @@ use RedBeanPHP\R;
|
||||
|
||||
class Comments extends BaseController {
|
||||
|
||||
public function getComment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
public function getComment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$comment = R::load('comment', (int)$args['id']);
|
||||
$comment = R::load('comment', (int)$args['id']);
|
||||
|
||||
if ($comment->id === 0) {
|
||||
$this->logger->addError('Attempt to load comment ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No comment found for ID ' .
|
||||
$args['id'] . '.');
|
||||
if ($comment->id === 0) {
|
||||
$this->logger->addError('Attempt to load comment ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No comment found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$task = R::load('task', $comment->task_id);
|
||||
$column = R::load('column', $task->column_id);
|
||||
$task = R::load('task', $comment->task_id);
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($comment);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($comment);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addComment($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$comment = R::dispense('comment');
|
||||
if (!BeanLoader::LoadComment($comment, $request->getBody())) {
|
||||
$comment->task_id = 0;
|
||||
}
|
||||
|
||||
$task = R::load('task', $comment->task_id);
|
||||
if ($task->id === 0) {
|
||||
$this->logger->addError('Add Comment: ', [$comment]);
|
||||
$this->apiJson->addAlert('error', 'Error adding comment. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($this->getBoardId($task->id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($comment);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added comment ' . $comment->id . '.',
|
||||
'', json_encode($comment), 'comment', $comment->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Comment added.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateComment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
|
||||
if (is_null($args) || !$args['id']) {
|
||||
$this->logger->addError('Update Comment: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating comment. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$comment = R::load('comment', (int)$args['id']);
|
||||
|
||||
// If User level, only the user that created the comment
|
||||
// may update it. If higher level, update is allowed.
|
||||
if ((int)$actor->security_level === SecurityLevel::USER) {
|
||||
if ($actor->id !== $comment->user_id) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'You do not have sufficient permissions ' .
|
||||
'to update this comment.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
$update = R::dispense('comment');
|
||||
$update->id = BeanLoader::LoadComment($update, json_encode($data))
|
||||
? $comment->id
|
||||
: 0;
|
||||
|
||||
if ($comment->id === 0 || ((int)$comment->id !== (int)$update->id)) {
|
||||
$this->logger->addError('Update Comment: ', [$comment]);
|
||||
$this->apiJson->addAlert('error', 'Error updating comment. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addComment($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($comment->task_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$comment = R::dispense('comment');
|
||||
if (!BeanLoader::LoadComment($comment, $request->getBody())) {
|
||||
$comment->task_id = 0;
|
||||
}
|
||||
R::store($update);
|
||||
|
||||
$task = R::load('task', $comment->task_id);
|
||||
if ($task->id === 0) {
|
||||
$this->logger->addError('Add Comment: ', [$comment]);
|
||||
$this->apiJson->addAlert('error', 'Error adding comment. ' .
|
||||
'Please try again.');
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated comment ' . $update->id,
|
||||
json_encode($comment), json_encode($update),
|
||||
'comment', $update->id);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Comment updated.');
|
||||
|
||||
if (!$this->checkBoardAccess($this->getBoardId($task->id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
$task = R::load('task', $comment->task_id);
|
||||
$this->apiJson->addData(R::exportAll($task));
|
||||
|
||||
R::store($comment);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added comment ' . $comment->id . '.',
|
||||
'', json_encode($comment), 'comment', $comment->id);
|
||||
public function removeComment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Comment added.');
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$comment = R::load('comment', $id);
|
||||
|
||||
// If User level, only the user that created the comment
|
||||
// may delete it. If higher level, delete is allowed.
|
||||
if ((int)$actor->security_level === SecurityLevel::USER) {
|
||||
if ($actor->id !== $comment->user_id) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'You do not have sufficient permissions ' .
|
||||
'to remove this comment.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
if ((int)$comment->id !== $id) {
|
||||
$this->logger->addError('Remove Comment: ', [$comment]);
|
||||
$this->apiJson->addAlert('error', 'Error removing comment. ' .
|
||||
'No comment found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateComment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$comment = R::load('comment', (int)$args['id']);
|
||||
|
||||
// If User level, only the user that created the comment
|
||||
// may update it. If higher level, update is allowed.
|
||||
if ((int)$actor->security_level === SecurityLevel::USER) {
|
||||
if ($actor->id !== $comment->user_id) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'You do not have sufficient permissions ' .
|
||||
'to update this comment.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
$update = R::dispense('comment');
|
||||
$update->id = BeanLoader::LoadComment($update, json_encode($data))
|
||||
? $comment->id
|
||||
: 0;
|
||||
|
||||
if ($comment->id === 0 || ((int)$comment->id !== (int)$update->id)) {
|
||||
$this->logger->addError('Update Comment: ', [$comment]);
|
||||
$this->apiJson->addAlert('error', 'Error updating comment. ' .
|
||||
'Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($comment->task_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($update);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated comment ' . $update->id,
|
||||
json_encode($comment), json_encode($update),
|
||||
'comment', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Comment updated.');
|
||||
|
||||
$task = R::load('task', $comment->task_id);
|
||||
$this->apiJson->addData(R::exportAll($task));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($comment->task_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
public function removeComment($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$before = $comment;
|
||||
R::trash($comment);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed comment ' . $before->id,
|
||||
json_encode($before), '', 'comment', $id);
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$comment = R::load('comment', $id);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Comment removed.');
|
||||
|
||||
// If User level, only the user that created the comment
|
||||
// may delete it. If higher level, delete is allowed.
|
||||
if ((int)$actor->security_level === SecurityLevel::USER) {
|
||||
if ($actor->id !== $comment->user_id) {
|
||||
$this->apiJson->addAlert('error',
|
||||
'You do not have sufficient permissions ' .
|
||||
'to remove this comment.');
|
||||
$task = R::load('task', $comment->task_id);
|
||||
$this->apiJson->addData(R::exportAll($task));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if ((int)$comment->id !== $id) {
|
||||
$this->logger->addError('Remove Comment: ', [$comment]);
|
||||
$this->apiJson->addAlert('error', 'Error removing comment. ' .
|
||||
'No comment found for ID ' . $id . '.');
|
||||
private function getBoardId($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($comment->task_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $comment;
|
||||
R::trash($comment);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed comment ' . $before->id,
|
||||
json_encode($before), '', 'comment', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Comment removed.');
|
||||
|
||||
$task = R::load('task', $comment->task_id);
|
||||
$this->apiJson->addData(R::exportAll($task));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function getBoardId($taskId) {
|
||||
$task = R::load('task', $taskId);
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
return $column->board_id;
|
||||
}
|
||||
return $column->board_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,22 @@
|
||||
<?php
|
||||
class Invalid extends BaseController {
|
||||
|
||||
public function noApi($request, $response) {
|
||||
$request; // Not used, but required for Slim Framework
|
||||
$this->apiJson->addAlert('error',
|
||||
'No API functionality at this endpoint.');
|
||||
public function noApi($request, $response) {
|
||||
$request; // Not used, but required for Slim Framework
|
||||
$this->apiJson->addAlert('error',
|
||||
'No API functionality at this endpoint.');
|
||||
|
||||
$apiReturn = new stdClass();
|
||||
$apiReturn->status = 'One of "success" or "failure".';
|
||||
$apiReturn->data = 'An array of data (JSON objects and/or arrays). ' .
|
||||
'The first object is a new JWT for the next request.';
|
||||
$apiReturn->alerts = 'An array of alerts, with "type" of "success", ' .
|
||||
'"error", "warn", or "info" and a "text" message.';
|
||||
$apiReturn = new stdClass();
|
||||
$apiReturn->status = 'One of "success" or "failure".';
|
||||
$apiReturn->data = 'An array of data (JSON objects and/or arrays). ' .
|
||||
'The first object is a new JWT for the next request.';
|
||||
$apiReturn->alerts = 'An array of alerts, with "type" of "success", ' .
|
||||
'"error", "warn", or "info" and a "text" message.';
|
||||
|
||||
$this->apiJson->addData($apiReturn);
|
||||
$this->apiJson->addData($apiReturn);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,370 +3,384 @@ use RedBeanPHP\R;
|
||||
|
||||
class Tasks extends BaseController {
|
||||
|
||||
public function getTask($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$task = R::load('task', (int)$args['id']);
|
||||
|
||||
if ((int)$task->id === 0) {
|
||||
$this->logger->addError('Attemt to load task ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No task found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($task->column_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($task);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function getTask($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
public function addTask($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$task = R::load('task', (int)$args['id']);
|
||||
|
||||
$task = R::dispense('task');
|
||||
BeanLoader::LoadTask($task, $request->getBody());
|
||||
if ((int)$task->id === 0) {
|
||||
$this->logger->addError('Attemt to load task ' .
|
||||
$args['id'] . ' failed.');
|
||||
$this->apiJson->addAlert('error', 'No task found for ID ' .
|
||||
$args['id'] . '.');
|
||||
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
if ((int)$column->id === 0) {
|
||||
$this->logger->addError('Add Task: ', [$task]);
|
||||
$this->apiJson->addAlert('error', 'Error adding task. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
R::store($task);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->updateTaskOrder($task, $actor, true);
|
||||
$this->checkAutomaticActions(null, $task);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added task ' . $task->title . '.',
|
||||
'', json_encode($task), 'task', $task->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Task ' .
|
||||
$task->title . ' added.');
|
||||
$this->apiJson->addData(R::exportAll($task));
|
||||
|
||||
$board = R::load('board', $column->board_id);
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateTask($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$task = R::load('task', (int)$args['id']);
|
||||
|
||||
$update = R::load('task', (int)$args['id']);
|
||||
$update->id = BeanLoader::LoadTask($update, $request->getBody())
|
||||
? $task->id
|
||||
: 0;
|
||||
|
||||
if ($task->id === 0 || ((int)$task->id !== (int)$update->id)) {
|
||||
$this->logger->addError('Update Task: ', [$task, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating task ' .
|
||||
$task->title . '. Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($task->column_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = R::exportAll($task);
|
||||
R::store($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);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated task ' . $task->title,
|
||||
json_encode($task), json_encode($update),
|
||||
'task', $update->id);
|
||||
|
||||
$boardId = $this->getBoardId($task->column_id);
|
||||
$board = R::load('board', $boardId);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Task ' .
|
||||
$update->title . ' updated.');
|
||||
$this->apiJson->addData(R::exportAll($update));
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($task->column_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
public function removeTask($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($task);
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$task = R::load('task', $id);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if ((int)$task->id !== $id || (int)$task->id === 0) {
|
||||
$this->logger->addError('Remove Task: ', [$task]);
|
||||
$this->apiJson->addAlert('error', 'Error removing task. ' .
|
||||
'No task found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$boardId = $this->getBoardId($task->column_id);
|
||||
|
||||
if (!$this->checkBoardAccess($boardId, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $task;
|
||||
R::trash($task);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->updateTaskOrder($task, $actor, false);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed task ' . $before->title,
|
||||
json_encode($before), '', 'task', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Task ' . $before->title . ' removed.');
|
||||
|
||||
$board = R::load('board', $boardId);
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function addTask($request, $response) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
private function getBoardId($columnId) {
|
||||
$column = R::load('column', $columnId);
|
||||
$task = R::dispense('task');
|
||||
BeanLoader::LoadTask($task, $request->getBody());
|
||||
|
||||
return $column->board_id;
|
||||
$column = R::load('column', $task->column_id);
|
||||
|
||||
if ((int)$column->id === 0) {
|
||||
$this->logger->addError('Add Task: ', [$task]);
|
||||
$this->apiJson->addAlert('error', 'Error adding task. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function sortTasks($a, $b) {
|
||||
return strcmp($a->position, $b->position);
|
||||
if (!$this->checkBoardAccess($column->board_id, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
private function updateTaskOrder($task, $user, $isNew) {
|
||||
$column = R::load('column', $task->column_id);
|
||||
$user_opts = R::load('useroption', $user->user_option_id);
|
||||
R::store($task);
|
||||
|
||||
usort($column->xownTaskList, array($this, 'sortTasks'));
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->updateTaskOrder($task, $actor, true);
|
||||
$this->checkAutomaticActions(null, $task);
|
||||
|
||||
$counter = 1;
|
||||
foreach ($column->xownTaskList as $task) {
|
||||
$task->position = $counter;
|
||||
$counter++;
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added task ' . $task->title . '.',
|
||||
'', json_encode($task), 'task', $task->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Task ' .
|
||||
$task->title . ' added.');
|
||||
$this->apiJson->addData(R::exportAll($task));
|
||||
|
||||
$board = R::load('board', $column->board_id);
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateTask($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
|
||||
if (is_null($args) || !array_key_exists('id', $args)) {
|
||||
$this->logger->addError('Update Task: ', [$data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating task. Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$task = R::load('task', (int)$args['id']);
|
||||
|
||||
$update = R::load('task', (int)$args['id']);
|
||||
$update->id = BeanLoader::LoadTask($update, $request->getBody())
|
||||
? $task->id
|
||||
: 0;
|
||||
|
||||
if ($task->id === 0 || ((int)$task->id !== (int)$update->id)) {
|
||||
$this->logger->addError('Update Task: ', [$task, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating task ' .
|
||||
$task->title . '. Please try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkBoardAccess(
|
||||
$this->getBoardId($task->column_id), $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = R::exportAll($task);
|
||||
R::store($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);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated task ' . $task->title,
|
||||
json_encode($task), json_encode($update),
|
||||
'task', $update->id);
|
||||
|
||||
$boardId = $this->getBoardId($task->column_id);
|
||||
$board = R::load('board', $boardId);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Task ' .
|
||||
$update->title . ' updated.');
|
||||
$this->apiJson->addData(R::exportAll($update));
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function removeTask($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response,
|
||||
SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$task = R::load('task', $id);
|
||||
|
||||
if ((int)$task->id !== $id || (int)$task->id === 0) {
|
||||
$this->logger->addError('Remove Task: ', [$task]);
|
||||
$this->apiJson->addAlert('error', 'Error removing task. ' .
|
||||
'No task found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$boardId = $this->getBoardId($task->column_id);
|
||||
|
||||
if (!$this->checkBoardAccess($boardId, $request)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$before = $task;
|
||||
R::trash($task);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->updateTaskOrder($task, $actor, false);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed task ' . $before->title,
|
||||
json_encode($before), '', 'task', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'Task ' . $before->title . ' removed.');
|
||||
|
||||
$board = R::load('board', $boardId);
|
||||
$this->apiJson->addData(R::exportAll($board));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function getBoardId($columnId) {
|
||||
$column = R::load('column', $columnId);
|
||||
|
||||
return $column->board_id;
|
||||
}
|
||||
|
||||
private function sortTasks($a, $b) {
|
||||
return strcmp($a->position, $b->position);
|
||||
}
|
||||
|
||||
private function updateTaskOrder($task, $user, $isNew) {
|
||||
$column = R::load('column', $task->column_id);
|
||||
$user_opts = R::load('useroption', $user->user_option_id);
|
||||
|
||||
usort($column->xownTaskList, array($this, 'sortTasks'));
|
||||
|
||||
$counter = 1;
|
||||
foreach ($column->xownTaskList as $task) {
|
||||
$task->position = $counter;
|
||||
$counter++;
|
||||
}
|
||||
|
||||
R::store($column);
|
||||
|
||||
if (!$isNew || $user_opts->new_tasks_at_bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lastTask = end($column->xownTaskList);
|
||||
$lastTask->position = 0;
|
||||
R::store($column);
|
||||
}
|
||||
|
||||
private function checkAutomaticActions($before, $after) {
|
||||
$boardId = $this->getBoardId(
|
||||
is_array($after) ? $after[0]['column_id'] : $after['column_id']
|
||||
);
|
||||
$autoActions = R::find('autoaction', ' board_id = ? ', [ $boardId ]);
|
||||
|
||||
foreach ($autoActions as $action) {
|
||||
switch ($action->trigger) {
|
||||
case ActionTrigger::MOVED_TO_COLUMN():
|
||||
if ($before[0]['column_id'] !== $after[0]['column_id'] &&
|
||||
$after[0]['column_id'] === (int)$action->source_id) {
|
||||
$this->alterTask($action, $after[0]['id']);
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionTrigger::ASSIGNED_TO_USER():
|
||||
$prevAssigned = $this->isInList($action->source_id,
|
||||
isset($before[0]['sharedUser']) ?
|
||||
$before[0]['sharedUser'] :
|
||||
[]);
|
||||
|
||||
if ($prevAssigned) {
|
||||
break;
|
||||
}
|
||||
|
||||
R::store($column);
|
||||
foreach ($after[0]['sharedUser'] as $user) {
|
||||
if ((int)$action->source_id === (int)$user['id']) {
|
||||
$this->alterTask($action, $after[0]['id']);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
if (!$isNew || $user_opts->new_tasks_at_bottom) {
|
||||
return;
|
||||
case ActionTrigger::ADDED_TO_CATEGORY():
|
||||
$prevAssigned = $this->isInList($action->source_id,
|
||||
isset($before[0]['sharedCategory']) ?
|
||||
$before[0]['sharedCategory'] :
|
||||
[]);
|
||||
if ($prevAssigned) {
|
||||
break;
|
||||
}
|
||||
|
||||
$lastTask = end($column->xownTaskList);
|
||||
$lastTask->position = 0;
|
||||
R::store($column);
|
||||
}
|
||||
|
||||
private function checkAutomaticActions($before, $after) {
|
||||
$boardId = $this->getBoardId($after[0]['column_id']);
|
||||
$autoActions = R::find('autoaction', ' board_id = ? ', [ $boardId ]);
|
||||
|
||||
foreach ($autoActions as $action) {
|
||||
switch ($action->trigger) {
|
||||
case ActionTrigger::MOVED_TO_COLUMN():
|
||||
if ($before[0]['column_id'] !== $after[0]['column_id'] &&
|
||||
$after[0]['column_id'] === (int)$action->source_id) {
|
||||
$this->alterTask($action, $after[0]['id']);
|
||||
}
|
||||
break;
|
||||
case ActionTrigger::ASSIGNED_TO_USER():
|
||||
$prevAssigned = $this->isInList($action->source_id,
|
||||
isset($before[0]['sharedUser']) ?
|
||||
$before[0]['sharedUser'] :
|
||||
[]);
|
||||
|
||||
if ($prevAssigned) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($after[0]['sharedUser'] as $user) {
|
||||
if ((int)$action->source_id === (int)$user['id']) {
|
||||
$this->alterTask($action, $after[0]['id']);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ActionTrigger::ADDED_TO_CATEGORY():
|
||||
$prevAssigned = $this->isInList($action->source_id,
|
||||
isset($before[0]['sharedCategory']) ?
|
||||
$before[0]['sharedCategory'] :
|
||||
[]);
|
||||
if ($prevAssigned) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($after[0]['sharedCategory'] as $category) {
|
||||
if ((int)$action->source_id === (int)$category['id']) {
|
||||
$this->alterTask($action, $after[0]['id']);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTrigger::POINTS_CHANGED():
|
||||
$points = (isset($before[0]['points'])) ?
|
||||
(int)$before[0]['points'] :
|
||||
0;
|
||||
|
||||
if ($points !== (int)$after[0]['points']) {
|
||||
$this->updateTaskColor($after[0]['id'],
|
||||
$points,
|
||||
$after[0]['points']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
foreach ($after[0]['sharedCategory'] as $category) {
|
||||
if ((int)$action->source_id === (int)$category['id']) {
|
||||
$this->alterTask($action, $after[0]['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
private function isInList($itemId, $list) {
|
||||
foreach ($list as $item) {
|
||||
if ((int)$item['id'] === (int)$itemId) {
|
||||
return true;
|
||||
}
|
||||
case ActionTrigger::POINTS_CHANGED():
|
||||
$points = (isset($before[0]['points'])) ?
|
||||
(int)$before[0]['points'] :
|
||||
0;
|
||||
|
||||
if ($points !== (int)$after[0]['points']) {
|
||||
$this->updateTaskColor($after[0]['id'],
|
||||
$points,
|
||||
$after[0]['points']);
|
||||
}
|
||||
break;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isInList($itemId, $list) {
|
||||
foreach ($list as $item) {
|
||||
if ((int)$item['id'] === (int)$itemId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private function alterTask($action, $taskId) {
|
||||
switch ($action->type) {
|
||||
case ActionType::SET_COLOR():
|
||||
$task = R::load('task', $taskId);
|
||||
$task->color = $action->change_to;
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task color changed by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
case ActionType::SET_CATEGORY():
|
||||
$task = R::load('task', $taskId);
|
||||
unset($task->sharedCategoryList);
|
||||
case ActionType::ADD_CATEGORY():
|
||||
if (!isset($task)) {
|
||||
$task = R::load('task', $taskId);
|
||||
}
|
||||
private function alterTask($action, $taskId) {
|
||||
switch ($action->type) {
|
||||
case ActionType::SET_COLOR():
|
||||
$task = R::load('task', $taskId);
|
||||
$task->color = $action->change_to;
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task color changed by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
|
||||
$cat = R::load('category', $action->change_to);
|
||||
$task->sharedCategoryList[] = $cat;
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task categories changed by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
|
||||
case ActionType::SET_ASSIGNEE():
|
||||
$task = R::load('task', $taskId);
|
||||
unset($task->sharedUserList);
|
||||
case ActionType::ADD_ASSIGNEE():
|
||||
if (!isset($task)) {
|
||||
$task = R::load('task', $taskId);
|
||||
}
|
||||
|
||||
$user = R::load('user', $action->change_to);
|
||||
$task->sharedUserList[] = $user;
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task assignees changed by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
|
||||
case ActionType::CLEAR_DUE_DATE():
|
||||
$task = R::load('task', $taskId);
|
||||
|
||||
if ($task->due_date === '') {
|
||||
break;
|
||||
}
|
||||
|
||||
$task->due_date = '';
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task due date cleared by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function updateTaskColor($taskId, $beforePoints, $afterPoints) {
|
||||
case ActionType::SET_CATEGORY():
|
||||
$task = R::load('task', $taskId);
|
||||
unset($task->sharedCategoryList);
|
||||
case ActionType::ADD_CATEGORY():
|
||||
if (!isset($task)) {
|
||||
$task = R::load('task', $taskId);
|
||||
$diff = (float)$beforePoints - (float)$afterPoints;
|
||||
}
|
||||
|
||||
// Steps should be between -255 and 255.
|
||||
// Negative = darker, positive = lighter
|
||||
$steps = max(-255, min(255, $diff * 10));
|
||||
$cat = R::load('category', $action->change_to);
|
||||
$task->sharedCategoryList[] = $cat;
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task categories changed by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
|
||||
// Normalize into a six character long hex string
|
||||
$hex = $task->color;
|
||||
$hex = str_replace('#', '', $hex);
|
||||
if (strlen($hex) == 3) {
|
||||
$hex = str_repeat(substr($hex, 0, 1), 2).
|
||||
str_repeat(substr($hex, 1, 1), 2).
|
||||
str_repeat(substr($hex, 2, 1), 2);
|
||||
}
|
||||
case ActionType::SET_ASSIGNEE():
|
||||
$task = R::load('task', $taskId);
|
||||
unset($task->sharedUserList);
|
||||
case ActionType::ADD_ASSIGNEE():
|
||||
if (!isset($task)) {
|
||||
$task = R::load('task', $taskId);
|
||||
}
|
||||
|
||||
// Split into three parts: R, G and B
|
||||
$colorParts = str_split($hex, 2);
|
||||
$newColor = '#';
|
||||
$user = R::load('user', $action->change_to);
|
||||
$task->sharedUserList[] = $user;
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task assignees changed by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
|
||||
foreach ($colorParts as $color) {
|
||||
// Convert to decimal
|
||||
$color = hexdec($color);
|
||||
// Adjust color
|
||||
$color = max(0, min(255, $color + $steps));
|
||||
// Make two char hex code
|
||||
$newColor .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
case ActionType::CLEAR_DUE_DATE():
|
||||
$task = R::load('task', $taskId);
|
||||
|
||||
$task->color = $newColor;
|
||||
if ($task->due_date === '') {
|
||||
break;
|
||||
}
|
||||
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task color changed by automatic action.');
|
||||
R::store($task);
|
||||
$task->due_date = '';
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task due date cleared by automatic action.');
|
||||
R::store($task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function updateTaskColor($taskId, $beforePoints, $afterPoints) {
|
||||
$task = R::load('task', $taskId);
|
||||
$diff = (float)$beforePoints - (float)$afterPoints;
|
||||
|
||||
// Steps should be between -255 and 255.
|
||||
// Negative = darker, positive = lighter
|
||||
$steps = max(-255, min(255, $diff * 10));
|
||||
|
||||
// Normalize into a six character long hex string
|
||||
$hex = $task->color;
|
||||
$hex = str_replace('#', '', $hex);
|
||||
if (strlen($hex) == 3) {
|
||||
$hex = str_repeat(substr($hex, 0, 1), 2).
|
||||
str_repeat(substr($hex, 1, 1), 2).
|
||||
str_repeat(substr($hex, 2, 1), 2);
|
||||
}
|
||||
|
||||
// Split into three parts: R, G and B
|
||||
$colorParts = str_split($hex, 2);
|
||||
$newColor = '#';
|
||||
|
||||
foreach ($colorParts as $color) {
|
||||
// Convert to decimal
|
||||
$color = hexdec($color);
|
||||
// Adjust color
|
||||
$color = max(0, min(255, $color + $steps));
|
||||
// Make two char hex code
|
||||
$newColor .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
$task->color = $newColor;
|
||||
|
||||
$this->apiJson->addAlert('info',
|
||||
'Task color changed by automatic action.');
|
||||
R::store($task);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,482 +3,482 @@ use RedBeanPHP\R;
|
||||
|
||||
class Users extends BaseController {
|
||||
|
||||
public function getAllUsers($request, $response) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
public function getAllUsers($request, $response) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$data = $this->getAllUsersCleaned($request);
|
||||
$this->apiJson->addData($data);
|
||||
$this->apiJson->setSuccess();
|
||||
$data = $this->getAllUsersCleaned($request);
|
||||
$this->apiJson->addData($data);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function getUser($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
|
||||
$userIds = $this->getUserIdsByBoardAccess(Auth::GetUserId($request));
|
||||
$user = R::load('user', $id);
|
||||
|
||||
if ($user->id === 0) {
|
||||
$this->logger->addError('Attempt to load user ' . $id .
|
||||
' failed.');
|
||||
$this->apiJson->addAlert('error', 'No user found for ID ' .
|
||||
$id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!in_array($id, $userIds)) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($this->cleanUser($user));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function addUser($request, $response) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
$user = R::dispense('user');
|
||||
|
||||
if (isset($data->username)) {
|
||||
if ($this->checkUsernameExists($data)) {
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
public function getUser($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
if (isset($data->password) &&
|
||||
$data->password === $data->password_verify) {
|
||||
$data->password_hash =
|
||||
password_hash($data->password, PASSWORD_BCRYPT);
|
||||
unset($data->password);
|
||||
unset($data->password_verify);
|
||||
}
|
||||
|
||||
$id = (int)$args['id'];
|
||||
if (!BeanLoader::LoadUser($user, json_encode($data))) {
|
||||
$user->id = -1;
|
||||
}
|
||||
|
||||
$userIds = $this->getUserIdsByBoardAccess(Auth::GetUserId($request));
|
||||
$user = R::load('user', $id);
|
||||
if ($user->id === -1) {
|
||||
$this->logger->addError('Add User: ', [$user]);
|
||||
$this->apiJson->addAlert('error', 'Error adding user. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
if ($user->id === 0) {
|
||||
$this->logger->addError('Attempt to load user ' . $id .
|
||||
' failed.');
|
||||
$this->apiJson->addAlert('error', 'No user found for ID ' .
|
||||
$id . '.');
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
$opts = R::dispense('useroption');
|
||||
$opts->new_tasks_at_bottom = true;
|
||||
$opts->show_animations = true;
|
||||
$opts->show_assignee = true;
|
||||
$opts->multiple_tasks_per_row = false;
|
||||
$opts->language = 'en';
|
||||
R::store($opts);
|
||||
|
||||
if (!in_array($id, $userIds)) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
$user->user_option_id = $opts->id;
|
||||
R::store($user);
|
||||
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
if (isset($data->default_board_id)) {
|
||||
$data->boardAccess[] = $data->default_board_id;
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($this->cleanUser($user));
|
||||
$data->id = $user->id;
|
||||
$this->updateBoardAccess($data, $request);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added user ' . $user->username . '.',
|
||||
'', json_encode($user), 'user', $user->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'User ' . $user->username . ' added.');
|
||||
$this->apiJson->addData($this->getAllUsersCleaned($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
public function updateUser($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
$user = R::load('user', (int)$args['id']);
|
||||
|
||||
if (!property_exists($data, 'id')) {
|
||||
$this->logger->addError('Update User: ', [$user, $data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating user. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$update = R::load('user', $data->id);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
if (!$this->checkUserAccess($actor, $user)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$data->password_hash = $user->password_hash;
|
||||
|
||||
if (isset($data->new_password) && isset($data->old_password)) {
|
||||
if (!$this->verifyPassword($data, $user)) {
|
||||
$this->logger->addError('Update User: ', [$user, $update]);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$data->password_hash =
|
||||
password_hash($data->new_password, PASSWORD_BCRYPT);
|
||||
unset($data->new_password);
|
||||
unset($data->old_password);
|
||||
}
|
||||
|
||||
public function addUser($request, $response) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$data->active_token = $user->active_token;
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
$user = R::dispense('user');
|
||||
if (isset($data->password) && $data->password !== '') {
|
||||
$data->password_hash =
|
||||
password_hash($data->password, PASSWORD_BCRYPT);
|
||||
unset($data->password);
|
||||
}
|
||||
|
||||
if (isset($data->username)) {
|
||||
if ($this->checkUsernameExists($data)) {
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
}
|
||||
BeanLoader::LoadUser($update, json_encode($data));
|
||||
|
||||
if (isset($data->password) &&
|
||||
$data->password === $data->password_verify) {
|
||||
$data->password_hash =
|
||||
password_hash($data->password, PASSWORD_BCRYPT);
|
||||
unset($data->password);
|
||||
unset($data->password_verify);
|
||||
}
|
||||
if ((int)$user->id !== (int)$update->id) {
|
||||
$this->logger->addError('Update User: ', [$user, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating user. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
if (!BeanLoader::LoadUser($user, json_encode($data))) {
|
||||
$user->id = -1;
|
||||
}
|
||||
|
||||
if ($user->id === -1) {
|
||||
$this->logger->addError('Add User: ', [$user]);
|
||||
$this->apiJson->addAlert('error', 'Error adding user. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$opts = R::dispense('useroption');
|
||||
$opts->new_tasks_at_bottom = true;
|
||||
$opts->show_animations = true;
|
||||
$opts->show_assignee = true;
|
||||
$opts->multiple_tasks_per_row = false;
|
||||
$opts->language = 'en';
|
||||
R::store($opts);
|
||||
|
||||
$user->user_option_id = $opts->id;
|
||||
R::store($user);
|
||||
|
||||
if (isset($data->default_board_id)) {
|
||||
$data->boardAccess[] = $data->default_board_id;
|
||||
}
|
||||
|
||||
$data->id = $user->id;
|
||||
$this->updateBoardAccess($data, $request);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' added user ' . $user->username . '.',
|
||||
'', json_encode($user), 'user', $user->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'User ' . $user->username . ' added.');
|
||||
$this->apiJson->addData($this->getAllUsersCleaned($request));
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if ($user->username !== $update->username) {
|
||||
if ($this->checkUsernameExists($update)) {
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateUser($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$this->updateDefaultBoardId($data, $user, $update);
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
$user = R::load('user', (int)$args['id']);
|
||||
$this->updateBoardAccess($data, $request);
|
||||
R::store($update);
|
||||
|
||||
if (!property_exists($data, 'id')) {
|
||||
$this->logger->addError('Update User: ', [$user, $data]);
|
||||
$this->apiJson->addAlert('error', 'Error updating user. ' .
|
||||
'Please check your entries and try again.');
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated user ' . $update->username,
|
||||
json_encode($user), json_encode($update),
|
||||
'user', $update->id);
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'User ' . $update->username . ' updated.');
|
||||
$this->apiJson->addData(json_encode($this->cleanUser($update)));
|
||||
|
||||
$update = R::load('user', $data->id);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if (!$this->checkUserAccess($actor, $user)) {
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$data->password_hash = $user->password_hash;
|
||||
|
||||
if (isset($data->new_password) && isset($data->old_password)) {
|
||||
if (!$this->verifyPassword($data, $user)) {
|
||||
$this->logger->addError('Update User: ', [$user, $update]);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$data->password_hash =
|
||||
password_hash($data->new_password, PASSWORD_BCRYPT);
|
||||
unset($data->new_password);
|
||||
unset($data->old_password);
|
||||
}
|
||||
|
||||
$data->active_token = $user->active_token;
|
||||
|
||||
if (isset($data->password) && $data->password !== '') {
|
||||
$data->password_hash =
|
||||
password_hash($data->password, PASSWORD_BCRYPT);
|
||||
unset($data->password);
|
||||
}
|
||||
|
||||
BeanLoader::LoadUser($update, json_encode($data));
|
||||
|
||||
if ((int)$user->id !== (int)$update->id) {
|
||||
$this->logger->addError('Update User: ', [$user, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating user. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
if ($user->username !== $update->username) {
|
||||
if ($this->checkUsernameExists($update)) {
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateDefaultBoardId($data, $user, $update);
|
||||
|
||||
$this->updateBoardAccess($data, $request);
|
||||
R::store($update);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated user ' . $update->username,
|
||||
json_encode($user), json_encode($update),
|
||||
'user', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'User ' . $update->username . ' updated.');
|
||||
$this->apiJson->addData(json_encode($this->cleanUser($update)));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
public function updateUserOptions($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
public function updateUserOptions($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$user = R::load('user', (int)$args['id']);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
$user = R::load('user', (int)$args['id']);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
if ($actor->id !== $user->id) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
if ($actor->id !== $user->id) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$data = $request->getBody();
|
||||
|
||||
$userOpts = R::load('useroption', $user->user_option_id);
|
||||
$update = R::load('useroption', json_decode($data)->id);
|
||||
|
||||
if (!BeanLoader::LoadUserOption($update, $data)) {
|
||||
$update->id = -1;
|
||||
}
|
||||
|
||||
if ($userOpts->id !== $update->id) {
|
||||
$this->logger->addError('Update User Options: ',
|
||||
[$userOpts, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating user options. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
R::store($update);
|
||||
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated user options',
|
||||
json_encode($userOpts), json_encode($update),
|
||||
'user_option', $update->id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'User options updated.');
|
||||
$this->apiJson->addData(json_encode($update));
|
||||
$this->apiJson->addData(json_encode($this->cleanUser($user)));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
public function toggleCollapsed($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
$data = $request->getBody();
|
||||
|
||||
$user = R::load('user', (int)$args['id']);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$userOpts = R::load('useroption', $user->user_option_id);
|
||||
$update = R::load('useroption', json_decode($data)->id);
|
||||
|
||||
if ($actor->id !== $user->id) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getBody());
|
||||
$collapsed = R::findOne('collapsed', ' user_id = ? AND column_id = ? ',
|
||||
[ $user->id, $data->id ]);
|
||||
|
||||
$makeNew = true;
|
||||
if (!is_null($collapsed)) {
|
||||
R::trash($collapsed);
|
||||
$makeNew = false;
|
||||
}
|
||||
|
||||
if ($makeNew) {
|
||||
$collapsed = R::dispense('collapsed');
|
||||
$collapsed->user_id = $user->id;
|
||||
$collapsed->column_id = $data->id;
|
||||
|
||||
R::store($collapsed);
|
||||
}
|
||||
|
||||
$allCollapsed = R::find('collapsed', ' user_id = ? ', [ $user->id ]);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData(R::exportAll($allCollapsed));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
if (!BeanLoader::LoadUserOption($update, $data)) {
|
||||
$update->id = -1;
|
||||
}
|
||||
|
||||
public function removeUser($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
if ($userOpts->id !== $update->id) {
|
||||
$this->logger->addError('Update User Options: ',
|
||||
[$userOpts, $update]);
|
||||
$this->apiJson->addAlert('error', 'Error updating user options. ' .
|
||||
'Please check your entries and try again.');
|
||||
|
||||
$id = (int)$args['id'];
|
||||
$user = R::load('user', $id);
|
||||
|
||||
if ((int)$user->id !== $id) {
|
||||
$this->logger->addError('Remove User: ', [$user]);
|
||||
$this->apiJson->addAlert('error', 'Error removing user. ' .
|
||||
'No user found for ID ' . $id . '.');
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
$before = $user;
|
||||
R::trash($user);
|
||||
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed user ' . $before->username,
|
||||
json_encode($before), '', 'user', $id);
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'User ' . $before->username . ' removed.');
|
||||
$this->apiJson->addData($this->getAllUsersCleaned($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function updateBoardAccess(&$userData, $request) {
|
||||
$boardIds = $this->getBoardIdsByAccess($userData->id);
|
||||
R::store($update);
|
||||
|
||||
if (isset($userData->boardAccess)) {
|
||||
$user = R::load('user', $userData->id);
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' updated user options',
|
||||
json_encode($userOpts), json_encode($update),
|
||||
'user_option', $update->id);
|
||||
|
||||
foreach ($userData->boardAccess as $boardId) {
|
||||
if (!in_array($boardId, $boardIds)) {
|
||||
$this->addUserToBoard((int)$boardId, $user, $request);
|
||||
}
|
||||
}
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'User options updated.');
|
||||
$this->apiJson->addData(json_encode($update));
|
||||
$this->apiJson->addData(json_encode($this->cleanUser($user)));
|
||||
|
||||
if (count(array_diff($userData->boardAccess, $boardIds))) {
|
||||
foreach ($boardIds as $removeId) {
|
||||
if (!in_array($removeId, $userData->boardAccess)) {
|
||||
$this->removeUserFromBoard($removeId, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
R::store($user);
|
||||
unset($userData->boardAccess);
|
||||
}
|
||||
public function toggleCollapsed($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::USER);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
private function addUserToBoard($boardId, $user, $request) {
|
||||
if ($boardId > 0 &&
|
||||
!Auth::HasBoardAccess($request, $boardId, $user->id)) {
|
||||
$board = R::load('board', $boardId);
|
||||
$board->sharedUserList[] = $user;
|
||||
R::store($board);
|
||||
}
|
||||
$user = R::load('user', (int)$args['id']);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
|
||||
if ($actor->id !== $user->id) {
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
|
||||
return $this->jsonResponse($response, 403);
|
||||
}
|
||||
|
||||
private function removeUserFromBoard($boardId, $user) {
|
||||
if ($boardId > 0) {
|
||||
$board = R::load('board', $boardId);
|
||||
unset($board->sharedUserList[$user->id]);
|
||||
R::store($board);
|
||||
}
|
||||
$data = json_decode($request->getBody());
|
||||
$collapsed = R::findOne('collapsed', ' user_id = ? AND column_id = ? ',
|
||||
[ $user->id, $data->id ]);
|
||||
|
||||
$makeNew = true;
|
||||
if (!is_null($collapsed)) {
|
||||
R::trash($collapsed);
|
||||
$makeNew = false;
|
||||
}
|
||||
|
||||
private function getAllUsersCleaned($request) {
|
||||
$userBeans = R::findAll('user');
|
||||
$userId = Auth::GetUserId($request);
|
||||
if ($makeNew) {
|
||||
$collapsed = R::dispense('collapsed');
|
||||
$collapsed->user_id = $user->id;
|
||||
$collapsed->column_id = $data->id;
|
||||
|
||||
$userIds = $this->getUserIdsByBoardAccess(Auth::GetUserId($request));
|
||||
|
||||
// If a user has no board access, they should still see themselves
|
||||
if (count($userIds) === 0) {
|
||||
$userIds[] = $userId;
|
||||
}
|
||||
|
||||
$actor = R::load('user', $userId);
|
||||
$isAdmin = ((int)$actor->security_level === SecurityLevel::ADMIN);
|
||||
|
||||
$data = [];
|
||||
foreach ($userBeans as $user) {
|
||||
if (in_array($user->id, $userIds) || $isAdmin) {
|
||||
$data[] = $this->cleanUser($user);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
R::store($collapsed);
|
||||
}
|
||||
|
||||
private function getBoardIdsByAccess($userId) {
|
||||
$boardIds = [];
|
||||
$allCollapsed = R::find('collapsed', ' user_id = ? ', [ $user->id ]);
|
||||
|
||||
$boards = R::getAll('SELECT board_id FROM board_user ' .
|
||||
'WHERE user_id = :user_id',
|
||||
[':user_id' => $userId]);
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData(R::exportAll($allCollapsed));
|
||||
|
||||
foreach ($boards as $board) {
|
||||
$boardIds[] = (int)$board['board_id'];
|
||||
}
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
return $boardIds;
|
||||
public function removeUser($request, $response, $args) {
|
||||
$status = $this->secureRoute($request, $response, SecurityLevel::ADMIN);
|
||||
if ($status !== 200) {
|
||||
return $this->jsonResponse($response, $status);
|
||||
}
|
||||
|
||||
private function getUserIdsByBoardAccess($userId) {
|
||||
$userIds = [];
|
||||
$boardIds = $this->getBoardIdsByAccess($userId);
|
||||
$id = (int)$args['id'];
|
||||
$user = R::load('user', $id);
|
||||
|
||||
foreach ($boardIds as $id) {
|
||||
$board = R::load('board', $id);
|
||||
if ((int)$user->id !== $id) {
|
||||
$this->logger->addError('Remove User: ', [$user]);
|
||||
$this->apiJson->addAlert('error', 'Error removing user. ' .
|
||||
'No user found for ID ' . $id . '.');
|
||||
|
||||
foreach ($board->sharedUserList as $user) {
|
||||
if (!in_array((int) $user->id, $userIds)) {
|
||||
$userIds[] = (int) $user->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $userIds;
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function cleanUser($user) {
|
||||
unset($user->password_hash);
|
||||
unset($user->active_token);
|
||||
$before = $user;
|
||||
R::trash($user);
|
||||
|
||||
$this->setBoardAccess($user);
|
||||
$actor = R::load('user', Auth::GetUserId($request));
|
||||
$this->dbLogger->logChange($actor->id,
|
||||
$actor->username . ' removed user ' . $before->username,
|
||||
json_encode($before), '', 'user', $id);
|
||||
|
||||
return $user;
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success',
|
||||
'User ' . $before->username . ' removed.');
|
||||
$this->apiJson->addData($this->getAllUsersCleaned($request));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
||||
private function updateBoardAccess(&$userData, $request) {
|
||||
$boardIds = $this->getBoardIdsByAccess($userData->id);
|
||||
|
||||
if (isset($userData->boardAccess)) {
|
||||
$user = R::load('user', $userData->id);
|
||||
|
||||
foreach ($userData->boardAccess as $boardId) {
|
||||
if (!in_array($boardId, $boardIds)) {
|
||||
$this->addUserToBoard((int)$boardId, $user, $request);
|
||||
}
|
||||
}
|
||||
|
||||
if (count(array_diff($userData->boardAccess, $boardIds))) {
|
||||
foreach ($boardIds as $removeId) {
|
||||
if (!in_array($removeId, $userData->boardAccess)) {
|
||||
$this->removeUserFromBoard($removeId, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R::store($user);
|
||||
unset($userData->boardAccess);
|
||||
}
|
||||
}
|
||||
|
||||
private function addUserToBoard($boardId, $user, $request) {
|
||||
if ($boardId > 0 &&
|
||||
!Auth::HasBoardAccess($request, $boardId, $user->id)) {
|
||||
$board = R::load('board', $boardId);
|
||||
$board->sharedUserList[] = $user;
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
private function removeUserFromBoard($boardId, $user) {
|
||||
if ($boardId > 0) {
|
||||
$board = R::load('board', $boardId);
|
||||
unset($board->sharedUserList[$user->id]);
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
private function getAllUsersCleaned($request) {
|
||||
$userBeans = R::findAll('user');
|
||||
$userId = Auth::GetUserId($request);
|
||||
|
||||
$userIds = $this->getUserIdsByBoardAccess(Auth::GetUserId($request));
|
||||
|
||||
// If a user has no board access, they should still see themselves
|
||||
if (count($userIds) === 0) {
|
||||
$userIds[] = $userId;
|
||||
}
|
||||
|
||||
private function setBoardAccess(&$user) {
|
||||
$user->board_access = [];
|
||||
$boards = RedBeanPHP\R::getAll('select bu.board_id, bu.user_id from ' .
|
||||
'board_user bu join board b on b.id = bu.board_id');
|
||||
$actor = R::load('user', $userId);
|
||||
$isAdmin = ((int)$actor->security_level === SecurityLevel::ADMIN);
|
||||
|
||||
foreach ($boards as $item) {
|
||||
if ((int)$user->id === (int)$item['user_id']) {
|
||||
$user->board_access[] = (int)$item['board_id'];
|
||||
}
|
||||
}
|
||||
$data = [];
|
||||
foreach ($userBeans as $user) {
|
||||
if (in_array($user->id, $userIds) || $isAdmin) {
|
||||
$data[] = $this->cleanUser($user);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkUsernameExists($data) {
|
||||
$existing = R::findOne('user', 'username = ?', [ $data->username ]);
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($existing) {
|
||||
$this->apiJson->addAlert('error', 'Username already exists. ' .
|
||||
'Change the username and try again.');
|
||||
return true;
|
||||
}
|
||||
private function getBoardIdsByAccess($userId) {
|
||||
$boardIds = [];
|
||||
|
||||
return false;
|
||||
$boards = R::getAll('SELECT board_id FROM board_user ' .
|
||||
'WHERE user_id = :user_id',
|
||||
[':user_id' => $userId]);
|
||||
|
||||
foreach ($boards as $board) {
|
||||
$boardIds[] = (int)$board['board_id'];
|
||||
}
|
||||
|
||||
private function checkUserAccess($actor, $user) {
|
||||
if ((int)$actor->id !== (int)$user->id) {
|
||||
if ((int)$actor->security_level === SecurityLevel::ADMIN) {
|
||||
return true;
|
||||
}
|
||||
return $boardIds;
|
||||
}
|
||||
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
return false;
|
||||
private function getUserIdsByBoardAccess($userId) {
|
||||
$userIds = [];
|
||||
$boardIds = $this->getBoardIdsByAccess($userId);
|
||||
|
||||
foreach ($boardIds as $id) {
|
||||
$board = R::load('board', $id);
|
||||
|
||||
foreach ($board->sharedUserList as $user) {
|
||||
if (!in_array((int) $user->id, $userIds)) {
|
||||
$userIds[] = (int) $user->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $userIds;
|
||||
}
|
||||
|
||||
private function cleanUser($user) {
|
||||
unset($user->password_hash);
|
||||
unset($user->active_token);
|
||||
|
||||
$this->setBoardAccess($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function setBoardAccess(&$user) {
|
||||
$user->board_access = [];
|
||||
$boards = RedBeanPHP\R::getAll('select bu.board_id, bu.user_id from ' .
|
||||
'board_user bu join board b on b.id = bu.board_id');
|
||||
|
||||
foreach ($boards as $item) {
|
||||
if ((int)$user->id === (int)$item['user_id']) {
|
||||
$user->board_access[] = (int)$item['board_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function checkUsernameExists($data) {
|
||||
$existing = R::findOne('user', 'username = ?', [ $data->username ]);
|
||||
|
||||
if ($existing) {
|
||||
$this->apiJson->addAlert('error', 'Username already exists. ' .
|
||||
'Change the username and try again.');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function checkUserAccess($actor, $user) {
|
||||
if ((int)$actor->id !== (int)$user->id) {
|
||||
if ((int)$actor->security_level === SecurityLevel::ADMIN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->apiJson->addAlert('error', 'Access restricted.');
|
||||
return false;
|
||||
}
|
||||
|
||||
private function verifyPassword($data, $user) {
|
||||
if (!password_verify($data->old_password, $user->password_hash)) {
|
||||
$this->apiJson->addAlert('error', 'Error updating user. ' .
|
||||
'Incorrect current password.');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
private function verifyPassword($data, $user) {
|
||||
if (!password_verify($data->old_password, $user->password_hash)) {
|
||||
$this->apiJson->addAlert('error', 'Error updating user. ' .
|
||||
'Incorrect current password.');
|
||||
return false;
|
||||
}
|
||||
|
||||
private function updateDefaultBoardId(&$data, $user, $update) {
|
||||
if ($user->default_board_id === $update->default_board_id ||
|
||||
(int)$update->default_board_id === 0) {
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset($data->boardAccess) &&
|
||||
!in_array($data->default_board_id, $data->boardAccess)) {
|
||||
$data->boardAccess[] = $data->default_board_id;
|
||||
}
|
||||
private function updateDefaultBoardId(&$data, $user, $update) {
|
||||
if ($user->default_board_id === $update->default_board_id ||
|
||||
(int)$update->default_board_id === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($data->boardAccess) &&
|
||||
!in_array($data->default_board_id, $data->boardAccess)) {
|
||||
$data->boardAccess[] = $data->default_board_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
class ActionTrigger extends Enum {
|
||||
const MOVED_TO_COLUMN = 1;
|
||||
const ASSIGNED_TO_USER = 2;
|
||||
const ADDED_TO_CATEGORY = 3;
|
||||
const POINTS_CHANGED = 4;
|
||||
const MOVED_TO_COLUMN = 1;
|
||||
const ASSIGNED_TO_USER = 2;
|
||||
const ADDED_TO_CATEGORY = 3;
|
||||
const POINTS_CHANGED = 4;
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,12 @@
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
class ActionType extends Enum {
|
||||
const SET_COLOR = 1;
|
||||
const SET_CATEGORY = 2;
|
||||
const ADD_CATEGORY = 3;
|
||||
const SET_ASSIGNEE = 4;
|
||||
const ADD_ASSIGNEE = 5;
|
||||
const CLEAR_DUE_DATE = 6;
|
||||
const ALTER_COLOR_BY_POINTS= 7;
|
||||
const SET_COLOR = 1;
|
||||
const SET_CATEGORY = 2;
|
||||
const ADD_CATEGORY = 3;
|
||||
const SET_ASSIGNEE = 4;
|
||||
const ADD_ASSIGNEE = 5;
|
||||
const CLEAR_DUE_DATE = 6;
|
||||
const ALTER_COLOR_BY_POINTS= 7;
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,22 @@
|
||||
<?php
|
||||
class ApiJson {
|
||||
public $status = 'failure';
|
||||
public $data = [];
|
||||
public $alerts = [];
|
||||
public $status = 'failure';
|
||||
public $data = [];
|
||||
public $alerts = [];
|
||||
|
||||
function setSuccess() {
|
||||
$this->status = 'success';
|
||||
}
|
||||
function setSuccess() {
|
||||
$this->status = 'success';
|
||||
}
|
||||
|
||||
function addData($obj) {
|
||||
$this->data[] = $obj;
|
||||
}
|
||||
function addData($obj) {
|
||||
$this->data[] = $obj;
|
||||
}
|
||||
|
||||
function addAlert($type, $text) {
|
||||
$this->alerts[] = [
|
||||
'type' => $type,
|
||||
'text' => $text
|
||||
];
|
||||
}
|
||||
function addAlert($type, $text) {
|
||||
$this->alerts[] = [
|
||||
'type' => $type,
|
||||
'text' => $text
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,300 +3,300 @@ use RedBeanPHP\R;
|
||||
|
||||
class BeanLoader {
|
||||
|
||||
public static function LoadAttachment(&$attachment, $json) {
|
||||
$data = json_decode($json);
|
||||
public static function LoadAttachment(&$attachment, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$attachment->filename = isset($data->filename) ? $data->filename : '';
|
||||
$attachment->name = isset($data->name) ? $data->name : '';
|
||||
$attachment->type = isset($data->type) ? $data->type : '';
|
||||
$attachment->user_id = isset($data->user_id) ? $data->user_id : -1;
|
||||
$attachment->timestamp = time();
|
||||
$attachment->task_id = isset($data->task_id) ? $data->task_id : -1;
|
||||
$attachment->filename = isset($data->filename) ? $data->filename : '';
|
||||
$attachment->name = isset($data->name) ? $data->name : '';
|
||||
$attachment->type = isset($data->type) ? $data->type : '';
|
||||
$attachment->user_id = isset($data->user_id) ? $data->user_id : -1;
|
||||
$attachment->timestamp = time();
|
||||
$attachment->task_id = isset($data->task_id) ? $data->task_id : -1;
|
||||
|
||||
if (!isset($data->filename) || !isset($data->name) ||
|
||||
!isset($data->type) || !isset($data->user_id) ||
|
||||
!isset($data->task_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!isset($data->filename) || !isset($data->name) ||
|
||||
!isset($data->type) || !isset($data->user_id) ||
|
||||
!isset($data->task_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function LoadAutoAction(&$action, $json) {
|
||||
$data = json_decode($json);
|
||||
return true;
|
||||
}
|
||||
|
||||
$action->trigger = isset($data->trigger) ? $data->trigger : -1;
|
||||
$action->source_id = isset($data->source_id) ? $data->source_id: -1;
|
||||
$action->type = isset($data->type) ? $data->type : '';
|
||||
$action->change_to = isset($data->change_to) ? $data->change_to: -1;
|
||||
$action->board_id = isset($data->board_id) ? $data->board_id: -1;
|
||||
public static function LoadAutoAction(&$action, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
if (!isset($data->trigger) || !isset($data->type) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
$action->trigger = isset($data->trigger) ? $data->trigger : -1;
|
||||
$action->source_id = isset($data->source_id) ? $data->source_id: -1;
|
||||
$action->type = isset($data->type) ? $data->type : '';
|
||||
$action->change_to = isset($data->change_to) ? $data->change_to: -1;
|
||||
$action->board_id = isset($data->board_id) ? $data->board_id: -1;
|
||||
|
||||
return true;
|
||||
if (!isset($data->trigger) || !isset($data->type) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function LoadBoard(&$board, $json) {
|
||||
$data = json_decode($json);
|
||||
return true;
|
||||
}
|
||||
|
||||
$board->name = isset($data->name) ? $data->name : '';
|
||||
$board->is_active = isset($data->is_active) ? $data->is_active : false;
|
||||
public static function LoadBoard(&$board, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
if (isset($data->categories)) {
|
||||
self::updateObjectList('category', 'LoadCategory',
|
||||
$board->xownCategoryList, $data->categories);
|
||||
}
|
||||
$board->name = isset($data->name) ? $data->name : '';
|
||||
$board->is_active = isset($data->is_active) ? $data->is_active : false;
|
||||
|
||||
if (isset($data->issue_trackers)) {
|
||||
self::updateObjectList('issuetracker', 'LoadIssueTracker',
|
||||
$board->xownIssueTrackerList,
|
||||
$data->issue_trackers);
|
||||
}
|
||||
|
||||
if (isset($data->columns)) {
|
||||
self::updateObjectList('column', 'LoadColumn',
|
||||
$board->xownColumnList, $data->columns);
|
||||
}
|
||||
|
||||
// Users do not get deleted when removed from a board
|
||||
if (isset($data->users)) {
|
||||
$board->sharedUserList = [];
|
||||
|
||||
foreach ($data->users as $userData) {
|
||||
$user = R::load('user', $userData->id);
|
||||
|
||||
if ((int)$user->id) {
|
||||
$board->sharedUserList[] = $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($data->name) || !isset($data->is_active) ||
|
||||
!isset($data->categories) || !isset($data->columns) ||
|
||||
!isset($data->issue_trackers) || !isset($data->users)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (isset($data->categories)) {
|
||||
self::updateObjectList('category', 'LoadCategory',
|
||||
$board->xownCategoryList, $data->categories);
|
||||
}
|
||||
|
||||
public static function LoadCategory(&$category, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$category->name = isset($data->name) ? $data->name : '';
|
||||
$category->default_task_color = isset($data->default_task_color)
|
||||
? $data->default_task_color : '';
|
||||
$category->board_id = isset($data->board_id) ? $data->board_id : -1;
|
||||
|
||||
if (!isset($data->name) || !isset($data->default_task_color) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (isset($data->issue_trackers)) {
|
||||
self::updateObjectList('issuetracker', 'LoadIssueTracker',
|
||||
$board->xownIssueTrackerList,
|
||||
$data->issue_trackers);
|
||||
}
|
||||
|
||||
public static function LoadColumn(&$column, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$column->name = isset($data->name) ? $data->name : '';
|
||||
$column->position = isset($data->position) ? $data->position : -1;
|
||||
$column->board_id = isset($data->board_id) ? $data->board_id : -1;
|
||||
$column->task_limit = isset($data->task_limit) ? $data->task_limit : 0;
|
||||
|
||||
if (isset($data->tasks)) {
|
||||
self::updateObjectList('task', 'LoadTask',
|
||||
$column->xownTaskList, $data->tasks);
|
||||
}
|
||||
|
||||
if (!isset($data->name) || !isset($data->position) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (isset($data->columns)) {
|
||||
self::updateObjectList('column', 'LoadColumn',
|
||||
$board->xownColumnList, $data->columns);
|
||||
}
|
||||
|
||||
public static function LoadComment(&$comment, $json) {
|
||||
$data = json_decode($json);
|
||||
// Users do not get deleted when removed from a board
|
||||
if (isset($data->users)) {
|
||||
$board->sharedUserList = [];
|
||||
|
||||
$comment->text = isset($data->text) ? $data->text : '';
|
||||
$comment->user_id = isset($data->user_id) ? $data->user_id : -1;
|
||||
$comment->task_id = isset($data->task_id) ? $data->task_id : -1;
|
||||
$comment->timestamp = isset($data->timestamp) ? $data->timestamp : -1;
|
||||
$comment->is_edited = isset($data->is_edited) ? $data->is_edited : false;
|
||||
foreach ($data->users as $userData) {
|
||||
$user = R::load('user', $userData->id);
|
||||
|
||||
if (!isset($data->text) || !isset($data->user_id) ||
|
||||
!isset($data->task_id) || !isset($data->timestamp)) {
|
||||
return false;
|
||||
if ((int)$user->id) {
|
||||
$board->sharedUserList[] = $user;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static function LoadIssueTracker(&$tracker, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$tracker->url = isset($data->url) ? $data->url : '';
|
||||
$tracker->regex = isset($data->regex) ? $data->regex : '';
|
||||
$tracker->board_id = isset($data->board_id) ? $data->board_id : -1;
|
||||
|
||||
if (!isset($data->url) || !isset($data->regex) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!isset($data->name) || !isset($data->is_active) ||
|
||||
!isset($data->categories) || !isset($data->columns) ||
|
||||
!isset($data->issue_trackers) || !isset($data->users)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function LoadTask(&$task, $json) {
|
||||
$data = json_decode($json);
|
||||
return true;
|
||||
}
|
||||
|
||||
$task->title = isset($data->title) ? $data->title : '';
|
||||
$task->description = isset($data->description)
|
||||
? $data->description : '';
|
||||
$task->color = isset($data->color) ? $data->color : '';
|
||||
$task->due_date = isset($data->due_date) ? $data->due_date : '';
|
||||
$task->points = isset($data->points) ? $data->points : 0;
|
||||
$task->position = isset($data->position) ? $data->position : -1;
|
||||
$task->column_id = isset($data->column_id) ? $data->column_id : -1;
|
||||
public static function LoadCategory(&$category, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
if (isset($data->comments)) {
|
||||
self::updateObjectList('comment', 'LoadComment',
|
||||
$task->xownCommentList, $data->comments);
|
||||
}
|
||||
$category->name = isset($data->name) ? $data->name : '';
|
||||
$category->default_task_color = isset($data->default_task_color)
|
||||
? $data->default_task_color : '';
|
||||
$category->board_id = isset($data->board_id) ? $data->board_id : -1;
|
||||
|
||||
if (isset($data->attachments)) {
|
||||
self::updateObjectList('attachment', 'LoadAttachment',
|
||||
$task->xownAttachmentList, $data->attachments);
|
||||
}
|
||||
|
||||
if (isset($data->assignees)) {
|
||||
$task->sharedUserList = [];
|
||||
|
||||
foreach ($data->assignees as $assignee) {
|
||||
$user = R::load('user', $assignee->id);
|
||||
|
||||
if ((int)$user->id) {
|
||||
$task->sharedUserList[] = $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data->categories)) {
|
||||
$task->sharedCategoryList = [];
|
||||
|
||||
foreach ($data->categories as $category) {
|
||||
$cat = R::load('category', $category->id);
|
||||
|
||||
if ((int)$cat->id) {
|
||||
$task->sharedCategoryList[] = $cat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($data->title) || !isset($data->position) ||
|
||||
!isset($data->column_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!isset($data->name) || !isset($data->default_task_color) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function LoadUser(&$user, $json) {
|
||||
$data = json_decode($json);
|
||||
return true;
|
||||
}
|
||||
|
||||
$user->security_level = isset($data->security_level)
|
||||
? $data->security_level : -1;
|
||||
$user->username = isset($data->username) ? $data->username : '';
|
||||
$user->email = isset($data->email) ? $data->email : '';
|
||||
$user->default_board_id = isset($data->default_board_id)
|
||||
? $data->default_board_id : -1;
|
||||
$user->user_option_id = isset($data->user_option_id)
|
||||
? $data->user_option_id : -1;
|
||||
$user->last_login = isset($data->last_login) ? $data->last_login : '';
|
||||
$user->password_hash = isset($data->password_hash)
|
||||
? $data->password_hash : '';
|
||||
public static function LoadColumn(&$column, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
if (!isset($data->security_level) || !isset($data->username)) {
|
||||
return false;
|
||||
}
|
||||
$column->name = isset($data->name) ? $data->name : '';
|
||||
$column->position = isset($data->position) ? $data->position : -1;
|
||||
$column->board_id = isset($data->board_id) ? $data->board_id : -1;
|
||||
$column->task_limit = isset($data->task_limit) ? $data->task_limit : 0;
|
||||
|
||||
return true;
|
||||
if (isset($data->tasks)) {
|
||||
self::updateObjectList('task', 'LoadTask',
|
||||
$column->xownTaskList, $data->tasks);
|
||||
}
|
||||
|
||||
public static function LoadUserOption(&$opts, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$opts->new_tasks_at_bottom = isset($data->new_tasks_at_bottom)
|
||||
? (boolean)$data->new_tasks_at_bottom : true;
|
||||
$opts->show_animations = isset($data->show_animations)
|
||||
? (boolean)$data->show_animations : true;
|
||||
$opts->show_assignee = isset($data->show_assignee)
|
||||
? (boolean)$data->show_assignee : true;
|
||||
$opts->multiple_tasks_per_row = isset($data->multiple_tasks_per_row)
|
||||
? (boolean)$data->multiple_tasks_per_row : false;
|
||||
$opts->language = isset($data->language)
|
||||
? $data->language : '';
|
||||
|
||||
if (!isset($data->new_tasks_at_bottom) ||
|
||||
!isset($data->show_animations) || !isset($data->show_assignee) ||
|
||||
!isset($data->multiple_tasks_per_row) || !isset($data->language)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!isset($data->name) || !isset($data->position) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function removeObjectsNotInData($type, &$dataList, &$objectList) {
|
||||
$dataIds = [];
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($dataList as $data) {
|
||||
if (isset($data->id)) {
|
||||
$dataIds[] = (int)$data->id;
|
||||
}
|
||||
}
|
||||
public static function LoadComment(&$comment, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
foreach ($objectList as $existing) {
|
||||
if (!in_array((int)$existing->id, $dataIds)) {
|
||||
$remove = R::load($type, $existing->id);
|
||||
R::trash($remove);
|
||||
}
|
||||
}
|
||||
$comment->text = isset($data->text) ? $data->text : '';
|
||||
$comment->user_id = isset($data->user_id) ? $data->user_id : -1;
|
||||
$comment->task_id = isset($data->task_id) ? $data->task_id : -1;
|
||||
$comment->timestamp = isset($data->timestamp) ? $data->timestamp : -1;
|
||||
$comment->is_edited = isset($data->is_edited) ? $data->is_edited : false;
|
||||
|
||||
if (!isset($data->text) || !isset($data->user_id) ||
|
||||
!isset($data->task_id) || !isset($data->timestamp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function loadObjectsFromData($type, $loadFunc, &$dataList,
|
||||
&$objectList) {
|
||||
foreach ($dataList as $obj) {
|
||||
$object = R::load($type, (isset($obj->id) ? $obj->id : 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
call_user_func_array(array(__CLASS__, $loadFunc),
|
||||
array(&$object, json_encode($obj)));
|
||||
$objectList[] = $object;
|
||||
}
|
||||
public static function LoadIssueTracker(&$tracker, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$tracker->url = isset($data->url) ? $data->url : '';
|
||||
$tracker->regex = isset($data->regex) ? $data->regex : '';
|
||||
$tracker->board_id = isset($data->board_id) ? $data->board_id : -1;
|
||||
|
||||
if (!isset($data->url) || !isset($data->regex) ||
|
||||
!isset($data->board_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function updateObjectList($type, $loadFunc,
|
||||
&$objectList = [],
|
||||
&$dataList = []) {
|
||||
if (count($objectList) && count($dataList)) {
|
||||
self::removeObjectsNotInData($type, $dataList, $objectList);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count($dataList)) {
|
||||
self::loadObjectsFromData($type, $loadFunc, $dataList, $objectList);
|
||||
}
|
||||
public static function LoadTask(&$task, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
// Remove all objects from existing boardlist when none in datalist
|
||||
if (!count($dataList) && count($objectList)) {
|
||||
foreach ($objectList as $obj) {
|
||||
R::trash($obj);
|
||||
}
|
||||
}
|
||||
$task->title = isset($data->title) ? $data->title : '';
|
||||
$task->description = isset($data->description)
|
||||
? $data->description : '';
|
||||
$task->color = isset($data->color) ? $data->color : '';
|
||||
$task->due_date = isset($data->due_date) ? $data->due_date : '';
|
||||
$task->points = isset($data->points) ? $data->points : 0;
|
||||
$task->position = isset($data->position) ? $data->position : -1;
|
||||
$task->column_id = isset($data->column_id) ? $data->column_id : -1;
|
||||
|
||||
if (isset($data->comments)) {
|
||||
self::updateObjectList('comment', 'LoadComment',
|
||||
$task->xownCommentList, $data->comments);
|
||||
}
|
||||
|
||||
if (isset($data->attachments)) {
|
||||
self::updateObjectList('attachment', 'LoadAttachment',
|
||||
$task->xownAttachmentList, $data->attachments);
|
||||
}
|
||||
|
||||
if (isset($data->assignees)) {
|
||||
$task->sharedUserList = [];
|
||||
|
||||
foreach ($data->assignees as $assignee) {
|
||||
$user = R::load('user', $assignee->id);
|
||||
|
||||
if ((int)$user->id) {
|
||||
$task->sharedUserList[] = $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data->categories)) {
|
||||
$task->sharedCategoryList = [];
|
||||
|
||||
foreach ($data->categories as $category) {
|
||||
$cat = R::load('category', $category->id);
|
||||
|
||||
if ((int)$cat->id) {
|
||||
$task->sharedCategoryList[] = $cat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($data->title) || !isset($data->position) ||
|
||||
!isset($data->column_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function LoadUser(&$user, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$user->security_level = isset($data->security_level)
|
||||
? $data->security_level : -1;
|
||||
$user->username = isset($data->username) ? $data->username : '';
|
||||
$user->email = isset($data->email) ? $data->email : '';
|
||||
$user->default_board_id = isset($data->default_board_id)
|
||||
? $data->default_board_id : -1;
|
||||
$user->user_option_id = isset($data->user_option_id)
|
||||
? $data->user_option_id : -1;
|
||||
$user->last_login = isset($data->last_login) ? $data->last_login : '';
|
||||
$user->password_hash = isset($data->password_hash)
|
||||
? $data->password_hash : '';
|
||||
|
||||
if (!isset($data->security_level) || !isset($data->username)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function LoadUserOption(&$opts, $json) {
|
||||
$data = json_decode($json);
|
||||
|
||||
$opts->new_tasks_at_bottom = isset($data->new_tasks_at_bottom)
|
||||
? (boolean)$data->new_tasks_at_bottom : true;
|
||||
$opts->show_animations = isset($data->show_animations)
|
||||
? (boolean)$data->show_animations : true;
|
||||
$opts->show_assignee = isset($data->show_assignee)
|
||||
? (boolean)$data->show_assignee : true;
|
||||
$opts->multiple_tasks_per_row = isset($data->multiple_tasks_per_row)
|
||||
? (boolean)$data->multiple_tasks_per_row : false;
|
||||
$opts->language = isset($data->language)
|
||||
? $data->language : '';
|
||||
|
||||
if (!isset($data->new_tasks_at_bottom) ||
|
||||
!isset($data->show_animations) || !isset($data->show_assignee) ||
|
||||
!isset($data->multiple_tasks_per_row) || !isset($data->language)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function removeObjectsNotInData($type, &$dataList, &$objectList) {
|
||||
$dataIds = [];
|
||||
|
||||
foreach ($dataList as $data) {
|
||||
if (isset($data->id)) {
|
||||
$dataIds[] = (int)$data->id;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($objectList as $existing) {
|
||||
if (!in_array((int)$existing->id, $dataIds)) {
|
||||
$remove = R::load($type, $existing->id);
|
||||
R::trash($remove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function loadObjectsFromData($type, $loadFunc, &$dataList,
|
||||
&$objectList) {
|
||||
foreach ($dataList as $obj) {
|
||||
$object = R::load($type, (isset($obj->id) ? $obj->id : 0));
|
||||
|
||||
call_user_func_array(array(__CLASS__, $loadFunc),
|
||||
array(&$object, json_encode($obj)));
|
||||
$objectList[] = $object;
|
||||
}
|
||||
}
|
||||
|
||||
private static function updateObjectList($type, $loadFunc,
|
||||
&$objectList = [],
|
||||
&$dataList = []) {
|
||||
if (count($objectList) && count($dataList)) {
|
||||
self::removeObjectsNotInData($type, $dataList, $objectList);
|
||||
}
|
||||
|
||||
if (count($dataList)) {
|
||||
self::loadObjectsFromData($type, $loadFunc, $dataList, $objectList);
|
||||
}
|
||||
|
||||
// Remove all objects from existing boardlist when none in datalist
|
||||
if (!count($dataList) && count($objectList)) {
|
||||
foreach ($objectList as $obj) {
|
||||
R::trash($obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,19 +2,19 @@
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class DbLogger {
|
||||
public static function logChange($user_id, $log_text, $before,
|
||||
$after, $item_type, $item_id) {
|
||||
$activity = R::dispense('activity');
|
||||
public static function logChange($user_id, $log_text, $before,
|
||||
$after, $item_type, $item_id) {
|
||||
$activity = R::dispense('activity');
|
||||
|
||||
$activity->user_id = $user_id;
|
||||
$activity->log_text = $log_text;
|
||||
$activity->before = $before;
|
||||
$activity->after = $after;
|
||||
$activity->item_type = $item_type;
|
||||
$activity->item_id = $item_id;
|
||||
$activity->timestamp = time();
|
||||
$activity->user_id = $user_id;
|
||||
$activity->log_text = $log_text;
|
||||
$activity->before = $before;
|
||||
$activity->after = $after;
|
||||
$activity->item_type = $item_type;
|
||||
$activity->item_id = $item_id;
|
||||
$activity->timestamp = time();
|
||||
|
||||
R::store($activity);
|
||||
}
|
||||
R::store($activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
final class SecurityLevel extends Enum {
|
||||
const ADMIN = 1;
|
||||
const BOARD_ADMIN = 2;
|
||||
const USER = 3;
|
||||
const UNPRIVILEGED = 4;
|
||||
const ADMIN = 1;
|
||||
const BOARD_ADMIN = 2;
|
||||
const USER = 3;
|
||||
const UNPRIVILEGED = 4;
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,7 @@ export class BoardDisplayComponent implements OnInit, OnDestroy, AfterContentIni
|
||||
}
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
this.dragula.dropModel('tasks-bag').subscribe((value: any) => {
|
||||
const taskId = +value[1].id;
|
||||
const toColumnId = +value[2].parentNode.id;
|
||||
@ -298,6 +299,7 @@ export class BoardDisplayComponent implements OnInit, OnDestroy, AfterContentIni
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
private changeTaskColumn(taskId: number, toColumnId: number) {
|
||||
const column = this.activeBoard.columns
|
||||
.find(col => col.id === toColumnId);
|
||||
|
@ -134,6 +134,7 @@ export class BoardService {
|
||||
);
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
uploadAttachment(attachment: Attachment, data: FormData): Observable<ApiResponse> {
|
||||
const headers = new HttpHeaders();
|
||||
const options = { headers, params: new HttpParams() };
|
||||
@ -151,7 +152,10 @@ export class BoardService {
|
||||
}
|
||||
|
||||
private defaultCallback = (err: any, text: string) => {
|
||||
console.log('default', err, text);
|
||||
if (err) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -281,10 +281,12 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
fileChange(file: File) {
|
||||
this.fileUpload = file;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
uploadFile() {
|
||||
if (!this.fileUpload) {
|
||||
this.notes.add({ type: 'error', text: this.strings.boards_taskNoFileError });
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
/* istanbul ignore next */
|
||||
@Component({
|
||||
selector: 'tb-calendar',
|
||||
templateUrl: './calendar.component.html'
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Component, Input, AfterViewInit } from '@angular/core';
|
||||
import * as Chartist from 'chartist';
|
||||
|
||||
/* istanbul ignore next */
|
||||
@Component({
|
||||
selector: 'tb-charts',
|
||||
templateUrl: './charts.component.html'
|
||||
|
@ -4,6 +4,7 @@ import { Title } from '@angular/platform-browser';
|
||||
// import { Charts } from './charts/charts.component';
|
||||
// import { Calendar } from './calendar/calendar.component';
|
||||
|
||||
/* istanbul ignore next */
|
||||
@Component({
|
||||
selector: 'tb-dashboard',
|
||||
templateUrl: './dashboard.component.html'
|
||||
|
@ -4,182 +4,182 @@ use Firebase\JWT\JWT;
|
||||
|
||||
class AppMock {
|
||||
|
||||
public function getContainer() {
|
||||
return new ContainerMock();
|
||||
}
|
||||
public function getContainer() {
|
||||
return new ContainerMock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$app = new AppMock();
|
||||
|
||||
class DataMock {
|
||||
public static function GetJwt($userId = 1) {
|
||||
Auth::CreateJwtSigningKey();
|
||||
public static function GetJwt($userId = 1) {
|
||||
Auth::CreateJwtSigningKey();
|
||||
|
||||
$key = R::load('jwt', 1);
|
||||
$key = R::load('jwt', 1);
|
||||
|
||||
$jwt = JWT::encode(array(
|
||||
'exp' => time() + (60 * 30), // 30 minutes
|
||||
'uid' => $userId,
|
||||
'mul' => 1
|
||||
), $key->secret);
|
||||
$jwt = JWT::encode(array(
|
||||
'exp' => time() + (60 * 30), // 30 minutes
|
||||
'uid' => $userId,
|
||||
'mul' => 1
|
||||
), $key->secret);
|
||||
|
||||
$user = R::load('user', $userId);
|
||||
$user->active_token = $jwt;
|
||||
R::store($user);
|
||||
$user = R::load('user', $userId);
|
||||
$user->active_token = $jwt;
|
||||
R::store($user);
|
||||
|
||||
return $jwt;
|
||||
}
|
||||
return $jwt;
|
||||
}
|
||||
|
||||
public static function CreateStandardUser() {
|
||||
$user = R::dispense('user');
|
||||
self::setUserDefaults($user);
|
||||
R::store($user);
|
||||
}
|
||||
public static function CreateStandardUser() {
|
||||
$user = R::dispense('user');
|
||||
self::setUserDefaults($user);
|
||||
R::store($user);
|
||||
}
|
||||
|
||||
public static function CreateBoardAdminUser() {
|
||||
$user = R::dispense('user');
|
||||
self::setUserDefaults($user);
|
||||
public static function CreateBoardAdminUser() {
|
||||
$user = R::dispense('user');
|
||||
self::setUserDefaults($user);
|
||||
|
||||
$user->username = 'boardadmin';
|
||||
$user->security_level = SecurityLevel::BOARD_ADMIN;
|
||||
R::store($user);
|
||||
}
|
||||
$user->username = 'boardadmin';
|
||||
$user->security_level = SecurityLevel::BOARD_ADMIN;
|
||||
R::store($user);
|
||||
}
|
||||
|
||||
public static function CreateUnprivilegedUser() {
|
||||
$user = R::dispense('user');
|
||||
self::setUserDefaults($user);
|
||||
public static function CreateUnprivilegedUser() {
|
||||
$user = R::dispense('user');
|
||||
self::setUserDefaults($user);
|
||||
|
||||
$user->username = 'badtester';
|
||||
$user->security_level = SecurityLevel::UNPRIVILEGED;
|
||||
R::store($user);
|
||||
}
|
||||
$user->username = 'badtester';
|
||||
$user->security_level = SecurityLevel::UNPRIVILEGED;
|
||||
R::store($user);
|
||||
}
|
||||
|
||||
public static function CreateBoard() {
|
||||
$board = R::dispense('board');
|
||||
$board->name = 'test';
|
||||
$board->is_active = true;
|
||||
}
|
||||
public static function CreateBoard() {
|
||||
$board = R::dispense('board');
|
||||
$board->name = 'test';
|
||||
$board->is_active = true;
|
||||
}
|
||||
|
||||
private static function setUserDefaults(&$user) {
|
||||
$user->username = 'tester';
|
||||
$user->security_level = SecurityLevel::USER;
|
||||
$user->password_hash = 'hashpass1234';
|
||||
$user->email = 'user@example.com';
|
||||
$user->default_board_id = 0;
|
||||
$user->user_option_id = 0;
|
||||
$user->last_login = 123456789;
|
||||
$user->active_token = '';
|
||||
}
|
||||
private static function setUserDefaults(&$user) {
|
||||
$user->username = 'tester';
|
||||
$user->security_level = SecurityLevel::USER;
|
||||
$user->password_hash = 'hashpass1234';
|
||||
$user->email = 'user@example.com';
|
||||
$user->default_board_id = 0;
|
||||
$user->user_option_id = 0;
|
||||
$user->last_login = 123456789;
|
||||
$user->active_token = '';
|
||||
}
|
||||
}
|
||||
|
||||
class LoggerMock {
|
||||
|
||||
public function addInfo() {
|
||||
}
|
||||
public function addInfo() {
|
||||
}
|
||||
|
||||
public function addError() {
|
||||
// Uncomment to log errors to file
|
||||
// The tests cover errors, so there will be plenty to sift through
|
||||
// $msg = func_get_arg(0);
|
||||
// $err = 'API ERROR: ' . $msg . PHP_EOL;
|
||||
public function addError() {
|
||||
// Uncomment to log errors to file
|
||||
// The tests cover errors, so there will be plenty to sift through
|
||||
// $msg = func_get_arg(0);
|
||||
// $err = 'API ERROR: ' . $msg . PHP_EOL;
|
||||
|
||||
// $objs = func_get_args();
|
||||
// array_splice($objs, 0, 1);
|
||||
// $objs = func_get_args();
|
||||
// array_splice($objs, 0, 1);
|
||||
|
||||
// ob_start();
|
||||
// foreach($objs as $obj) {
|
||||
// var_dump($obj);
|
||||
// }
|
||||
// $strings = ob_get_clean();
|
||||
// ob_start();
|
||||
// foreach($objs as $obj) {
|
||||
// var_dump($obj);
|
||||
// }
|
||||
// $strings = ob_get_clean();
|
||||
|
||||
// file_put_contents('tests.log', [$err, $strings], FILE_APPEND);
|
||||
}
|
||||
// file_put_contents('tests.log', [$err, $strings], FILE_APPEND);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ContainerMock {
|
||||
|
||||
public function get() {
|
||||
return new LoggerMock();
|
||||
}
|
||||
public function get() {
|
||||
return new LoggerMock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RequestMock {
|
||||
public $invalidPayload = false;
|
||||
public $payload = null;
|
||||
public $hasHeader = true;
|
||||
public $header = null;
|
||||
public $throwInHeader = false;
|
||||
public $invalidPayload = false;
|
||||
public $payload = null;
|
||||
public $hasHeader = true;
|
||||
public $header = null;
|
||||
public $throwInHeader = false;
|
||||
|
||||
public function getBody() {
|
||||
if ($this->invalidPayload) {
|
||||
return '{}';
|
||||
}
|
||||
|
||||
if ($this->payload) {
|
||||
return json_encode($this->payload);
|
||||
}
|
||||
|
||||
return '';
|
||||
public function getBody() {
|
||||
if ($this->invalidPayload) {
|
||||
return '{}';
|
||||
}
|
||||
|
||||
public function hasHeader() {
|
||||
return $this->hasHeader;
|
||||
if ($this->payload) {
|
||||
return json_encode($this->payload);
|
||||
}
|
||||
|
||||
public function getHeader($header) {
|
||||
if ($this->throwInHeader) {
|
||||
throw new Exception();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($this->header) {
|
||||
return $this->header;
|
||||
}
|
||||
public function hasHeader() {
|
||||
return $this->hasHeader;
|
||||
}
|
||||
|
||||
return $header;
|
||||
public function getHeader($header) {
|
||||
if ($this->throwInHeader) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
if ($this->header) {
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
return $header;
|
||||
}
|
||||
}
|
||||
|
||||
class ResponseMock {
|
||||
public $status = 200;
|
||||
public $body;
|
||||
public $status = 200;
|
||||
public $body;
|
||||
|
||||
public function __construct() {
|
||||
$this->body = new RequestBodyMock();
|
||||
}
|
||||
public function __construct() {
|
||||
$this->body = new RequestBodyMock();
|
||||
}
|
||||
|
||||
public function withJson($apiJson) {
|
||||
return $apiJson;
|
||||
}
|
||||
public function withJson($apiJson) {
|
||||
return $apiJson;
|
||||
}
|
||||
|
||||
public function withStatus($status) {
|
||||
$this->status = $status;
|
||||
public function withStatus($status) {
|
||||
$this->status = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatusCode() {
|
||||
return $this->status;
|
||||
}
|
||||
public function getStatusCode() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function getBody() {
|
||||
return $this->body;
|
||||
}
|
||||
public function getBody() {
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RequestBodyMock {
|
||||
public $data;
|
||||
public $data;
|
||||
|
||||
public function __toString() {
|
||||
return $this->data;
|
||||
}
|
||||
public function __toString() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function write($string) {
|
||||
$this->data = $string;
|
||||
}
|
||||
public function write($string) {
|
||||
$this->data = $string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,96 +3,96 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class ActivityTest extends PHPUnit\Framework\TestCase {
|
||||
private $activity;
|
||||
private $activity;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->activity = new Activity(new ContainerMock());
|
||||
}
|
||||
$this->activity = new Activity(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetActivityInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
public function testGetActivityInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
|
||||
$args = [];
|
||||
$args['type'] = 'task';
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['type'] = 'task';
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->activity->getActivity($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
$actual = $this->activity->getActivity($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testGetActivityForbidden() {
|
||||
$this->setupTaskActivity();
|
||||
public function testGetActivityForbidden() {
|
||||
$this->setupTaskActivity();
|
||||
|
||||
$args = [];
|
||||
$args['type'] = 'task';
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['type'] = 'task';
|
||||
$args['id'] = 1;
|
||||
|
||||
DataMock::CreateBoardAdminUser();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->activity->getActivity($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.', $actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->activity->getActivity($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetActivityForTask() {
|
||||
$this->setupTaskActivity();
|
||||
public function testGetActivityForTask() {
|
||||
$this->setupTaskActivity();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['type'] = 'task';
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['type'] = 'task';
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->activity->getActivity($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(3, count($actual->data[1]));
|
||||
}
|
||||
$actual = $this->activity->getActivity($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(3, count($actual->data[1]));
|
||||
}
|
||||
|
||||
private function setupTaskActivity() {
|
||||
$task = R::dispense('task');
|
||||
$comment = R::dispense('comment');
|
||||
$attachment = R::dispense('attachment');
|
||||
$task->ownComment[] = $comment;
|
||||
$task->ownAttachment[] = $attachment;
|
||||
R::store($task);
|
||||
private function setupTaskActivity() {
|
||||
$task = R::dispense('task');
|
||||
$comment = R::dispense('comment');
|
||||
$attachment = R::dispense('attachment');
|
||||
$task->ownComment[] = $comment;
|
||||
$task->ownAttachment[] = $attachment;
|
||||
R::store($task);
|
||||
|
||||
$activity = R::dispense('activity');
|
||||
$activity->item_type = 'task';
|
||||
$activity->item_id = 1;
|
||||
$activity->log_text = 'test change';
|
||||
$activity->timestamp = time();
|
||||
R::store($activity);
|
||||
$activity = R::dispense('activity');
|
||||
$activity->item_type = 'task';
|
||||
$activity->item_id = 1;
|
||||
$activity->log_text = 'test change';
|
||||
$activity->timestamp = time();
|
||||
R::store($activity);
|
||||
|
||||
$activity = R::dispense('activity');
|
||||
$activity->item_type = 'task';
|
||||
$activity->item_id = 1;
|
||||
$activity->log_text = 'test change';
|
||||
$activity->timestamp = time();
|
||||
R::store($activity);
|
||||
$activity = R::dispense('activity');
|
||||
$activity->item_type = 'task';
|
||||
$activity->item_id = 1;
|
||||
$activity->log_text = 'test change';
|
||||
$activity->timestamp = time();
|
||||
R::store($activity);
|
||||
|
||||
$activity = R::dispense('activity');
|
||||
$activity->item_type = 'task';
|
||||
$activity->item_id = 1;
|
||||
$activity->log_text = 'test change';
|
||||
$activity->timestamp = time() + 10;
|
||||
R::store($activity);
|
||||
}
|
||||
$activity = R::dispense('activity');
|
||||
$activity->item_type = 'task';
|
||||
$activity->item_id = 1;
|
||||
$activity->log_text = 'test change';
|
||||
$activity->timestamp = time() + 10;
|
||||
R::store($activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,231 +3,231 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class AttachmentsTest extends PHPUnit\Framework\TestCase {
|
||||
private $attachments;
|
||||
private $attachments;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
}
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetAttachment() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testGetAttachment() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No attachment found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No attachment found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
|
||||
$this->createAttachment();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$this->createAttachment();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
|
||||
public function testGetAttachmentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
public function testGetAttachmentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testGetAttachmentForbidden() {
|
||||
$this->createAttachment();
|
||||
public function testGetAttachmentForbidden() {
|
||||
$this->createAttachment();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->attachments->getAttachment(new RequestMock(),
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
$actual = $this->attachments->getAttachment(new RequestMock(),
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
|
||||
DataMock::CreateBoardAdminUser();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->getAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddAttachment() {
|
||||
$task = R::dispense('task');
|
||||
R::store($task);
|
||||
public function testAddAttachment() {
|
||||
$task = R::dispense('task');
|
||||
R::store($task);
|
||||
|
||||
$data = new stdClass();
|
||||
$data->filename = 'test';
|
||||
$data->name = 'test.png';
|
||||
$data->type = 'image';
|
||||
$data->user_id = 1;
|
||||
$data->task_id = 1;
|
||||
$data = new stdClass();
|
||||
$data->filename = 'test';
|
||||
$data->name = 'test.png';
|
||||
$data->type = 'image';
|
||||
$data->user_id = 1;
|
||||
$data->task_id = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Attachment added.', $actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Attachment added.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddAttachmentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testAddAttachmentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testAddAttachmentForbidden() {
|
||||
$task = R::dispense('task');
|
||||
R::store($task);
|
||||
public function testAddAttachmentForbidden() {
|
||||
$task = R::dispense('task');
|
||||
R::store($task);
|
||||
|
||||
$attachment = new stdClass();
|
||||
$attachment->filename = "test";
|
||||
$attachment->name = 'test.png';
|
||||
$attachment->type = 'image';
|
||||
$attachment->user_id = 1;
|
||||
$attachment->task_id = 1;
|
||||
$attachment = new stdClass();
|
||||
$attachment->filename = "test";
|
||||
$attachment->name = 'test.png';
|
||||
$attachment->type = 'image';
|
||||
$attachment->user_id = 1;
|
||||
$attachment->task_id = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $attachment;
|
||||
$request = new RequestMock();
|
||||
$request->payload = $attachment;
|
||||
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
$this->attachments = new Attachments(new ContainerMock());
|
||||
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->addAttachment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveAttachment() {
|
||||
$this->createAttachment();
|
||||
public function testRemoveAttachment() {
|
||||
$this->createAttachment();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Attachment file.png removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Attachment file.png removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$this->createAttachment();
|
||||
public function testRemoveUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$this->createAttachment();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveAttachmentUserSecurity() {
|
||||
$this->createAttachment();
|
||||
DataMock::CreateStandardUser();
|
||||
public function testRemoveAttachmentUserSecurity() {
|
||||
$this->createAttachment();
|
||||
DataMock::CreateStandardUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('You do not have sufficient permissions to ' .
|
||||
'remove this attachment.', $actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('You do not have sufficient permissions to ' .
|
||||
'remove this attachment.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveAttachmentForbidden() {
|
||||
$this->createAttachment();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testRemoveAttachmentForbidden() {
|
||||
$this->createAttachment();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveBadAttachment() {
|
||||
$this->createAttachment();
|
||||
public function testRemoveBadAttachment() {
|
||||
$this->createAttachment();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such attachment
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such attachment
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Error removing attachment. ' .
|
||||
'No attachment found for ID 2.', $actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->attachments->removeAttachment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Error removing attachment. ' .
|
||||
'No attachment found for ID 2.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
private function createAttachment() {
|
||||
$board = R::dispense('board');
|
||||
$column = R::dispense('column');
|
||||
$task = R::dispense('task');
|
||||
$attachment = R::dispense('attachment');
|
||||
private function createAttachment() {
|
||||
$board = R::dispense('board');
|
||||
$column = R::dispense('column');
|
||||
$task = R::dispense('task');
|
||||
$attachment = R::dispense('attachment');
|
||||
|
||||
$attachment->name = 'file.png';
|
||||
$attachment->user_id = 1;
|
||||
$attachment->name = 'file.png';
|
||||
$attachment->user_id = 1;
|
||||
|
||||
$task->xownAttachmentList[] = $attachment;
|
||||
$column->xownTaskList[] = $task;
|
||||
$board->xownColumnList[] = $column;
|
||||
R::store($board);
|
||||
}
|
||||
$task->xownAttachmentList[] = $attachment;
|
||||
$column->xownTaskList[] = $task;
|
||||
$board->xownColumnList[] = $column;
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,275 +3,275 @@ use RedBeanPHP\R;
|
||||
use Firebase\JWT\JWT;
|
||||
|
||||
class AuthTest extends PHPUnit\Framework\TestCase {
|
||||
private $auth;
|
||||
private $auth;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
}
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testHasBoardAccess() {
|
||||
$user = R::dispense('user');
|
||||
public function testHasBoardAccess() {
|
||||
$user = R::dispense('user');
|
||||
|
||||
$board = R::dispense('board');
|
||||
$board->sharedUserList[] = $user;
|
||||
R::store($board);
|
||||
$board = R::dispense('board');
|
||||
$board->sharedUserList[] = $user;
|
||||
R::store($board);
|
||||
|
||||
$hasAccess = Auth::HasBoardAccess(new RequestMock(), 1, 1);
|
||||
$this->assertEquals(true, $hasAccess);
|
||||
$hasAccess = Auth::HasBoardAccess(new RequestMock(), 1, 1);
|
||||
$this->assertEquals(true, $hasAccess);
|
||||
|
||||
$user->security_level = SecurityLevel::ADMIN;
|
||||
R::store($user);
|
||||
$user->security_level = SecurityLevel::ADMIN;
|
||||
R::store($user);
|
||||
|
||||
$hasAccess = Auth::HasBoardAccess(new RequestMock(), 1, 1);
|
||||
$this->assertEquals(true, $hasAccess);
|
||||
}
|
||||
$hasAccess = Auth::HasBoardAccess(new RequestMock(), 1, 1);
|
||||
$this->assertEquals(true, $hasAccess);
|
||||
}
|
||||
|
||||
public function testCreateInitialAdmin() {
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function testCreateInitialAdmin() {
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$admin = R::load('user', 1);
|
||||
$admin = R::load('user', 1);
|
||||
|
||||
$this->assertEquals(1, (int) $admin->id);
|
||||
$this->assertEquals('admin', $admin->username);
|
||||
$this->assertEquals(1, (int) $admin->id);
|
||||
$this->assertEquals('admin', $admin->username);
|
||||
|
||||
// Call again to verify only one is created
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
$this->assertEquals(1, R::count('user'));
|
||||
}
|
||||
// Call again to verify only one is created
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
$this->assertEquals(1, R::count('user'));
|
||||
}
|
||||
|
||||
public function testCreateJwtSigningKey() {
|
||||
Auth::CreateJwtSigningKey();
|
||||
public function testCreateJwtSigningKey() {
|
||||
Auth::CreateJwtSigningKey();
|
||||
|
||||
$jwt = R::load('jwt', 1);
|
||||
$jwt = R::load('jwt', 1);
|
||||
|
||||
$this->assertEquals(1, (int) $jwt->id);
|
||||
$this->assertTrue(strlen($jwt->secret) > 1);
|
||||
$this->assertEquals(1, (int) $jwt->id);
|
||||
$this->assertTrue(strlen($jwt->secret) > 1);
|
||||
|
||||
// Call again to verify only one is created
|
||||
Auth::CreateJwtSigningKey();
|
||||
$this->assertEquals(1, R::count('jwt'));
|
||||
}
|
||||
// Call again to verify only one is created
|
||||
Auth::CreateJwtSigningKey();
|
||||
$this->assertEquals(1, R::count('jwt'));
|
||||
}
|
||||
|
||||
public function testValidateTokenFailures() {
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
public function testValidateTokenFailures() {
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
|
||||
$actual = Auth::ValidateToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals(400, $actual->status);
|
||||
$actual = Auth::ValidateToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals(400, $actual->status);
|
||||
|
||||
$actual = Auth::ValidateToken(new RequestMock(),
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(401, $actual->status);
|
||||
$actual = Auth::ValidateToken(new RequestMock(),
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(401, $actual->status);
|
||||
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$user = R::load('user', 1);
|
||||
$user->active_token = 'whatever';
|
||||
R::store($user);
|
||||
$user = R::load('user', 1);
|
||||
$user->active_token = 'whatever';
|
||||
R::store($user);
|
||||
|
||||
$actual = Auth::ValidateToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals(401, $actual->status);
|
||||
}
|
||||
$actual = Auth::ValidateToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals(401, $actual->status);
|
||||
}
|
||||
|
||||
public function testValidateToken() {
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
public function testValidateToken() {
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
|
||||
$jwtKey = R::load('jwt', 1);
|
||||
$admin = R::load('user', 1);
|
||||
$jwtKey = R::load('jwt', 1);
|
||||
$admin = R::load('user', 1);
|
||||
|
||||
$token = JWT::encode(array(
|
||||
'exp' => time() + 600,
|
||||
'uid' => 1,
|
||||
'mul' => 1
|
||||
), $jwtKey->secret);
|
||||
$token = JWT::encode(array(
|
||||
'exp' => time() + 600,
|
||||
'uid' => 1,
|
||||
'mul' => 1
|
||||
), $jwtKey->secret);
|
||||
|
||||
$admin->active_token = $token;
|
||||
R::store($admin);
|
||||
$admin->active_token = $token;
|
||||
R::store($admin);
|
||||
|
||||
$response = new ResponseMock();
|
||||
$request = new RequestMock();
|
||||
$request->header = [$token];
|
||||
$response = new ResponseMock();
|
||||
$request = new RequestMock();
|
||||
$request->header = [$token];
|
||||
|
||||
Auth::ValidateToken($request, $response,
|
||||
new ContainerMock());
|
||||
$this->assertEquals(200, $response->status);
|
||||
}
|
||||
Auth::ValidateToken($request, $response,
|
||||
new ContainerMock());
|
||||
$this->assertEquals(200, $response->status);
|
||||
}
|
||||
|
||||
public function testGetUserId() {
|
||||
Auth::CreateJwtSigningKey();
|
||||
$jwtKey = R::load('jwt', 1);
|
||||
public function testGetUserId() {
|
||||
Auth::CreateJwtSigningKey();
|
||||
$jwtKey = R::load('jwt', 1);
|
||||
|
||||
$token = JWT::encode(array(
|
||||
'exp' => time() + 600,
|
||||
'uid' => 1,
|
||||
'mul' => 1
|
||||
), $jwtKey->secret);
|
||||
$token = JWT::encode(array(
|
||||
'exp' => time() + 600,
|
||||
'uid' => 1,
|
||||
'mul' => 1
|
||||
), $jwtKey->secret);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [$token];
|
||||
$request = new RequestMock();
|
||||
$request->header = [$token];
|
||||
|
||||
$actual = Auth::GetUserId($request);
|
||||
$this->assertEquals(1, $actual);
|
||||
$actual = Auth::GetUserId($request);
|
||||
$this->assertEquals(1, $actual);
|
||||
|
||||
$request->throwInHeader = true;
|
||||
$actual = Auth::GetUserId($request);
|
||||
$this->assertEquals(-1, $actual);
|
||||
}
|
||||
$request->throwInHeader = true;
|
||||
$actual = Auth::GetUserId($request);
|
||||
$this->assertEquals(-1, $actual);
|
||||
}
|
||||
|
||||
public function testLogin() {
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
public function testLogin() {
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request->payload->password = 'asdf';
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request->payload->password = 'asdf';
|
||||
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testLogout() {
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
public function testLogout() {
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$jwt = $actual->data[0];
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$jwt = $actual->data[0];
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [$jwt];
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [$jwt];
|
||||
|
||||
$actual = $this->auth->logout($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$actual = $this->auth->logout($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testLogoutFailures() {
|
||||
$actual = $this->auth->logout(new RequestMock(),
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
public function testLogoutFailures() {
|
||||
$actual = $this->auth->logout(new RequestMock(),
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->hasHeader = false;
|
||||
|
||||
$actual = $this->auth->logout($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->auth->logout($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testAuthenticate() {
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
public function testAuthenticate() {
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
|
||||
$collapsed = R::dispense('collapsed');
|
||||
$collapsed->user_id = 1;
|
||||
$collapsed->column_id = 1;
|
||||
R::store($collapsed);
|
||||
$collapsed = R::dispense('collapsed');
|
||||
$collapsed->user_id = 1;
|
||||
$collapsed->column_id = 1;
|
||||
R::store($collapsed);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
|
||||
$jwt = $actual->data[0];
|
||||
$jwt = $actual->data[0];
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [$jwt];
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [$jwt];
|
||||
|
||||
$actual = $this->auth->authenticate($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$actual = $this->auth->authenticate($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request->hasHeader = false;
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request->hasHeader = false;
|
||||
|
||||
$actual = $this->auth->authenticate($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$actual = $this->auth->authenticate($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = ['not a valid JWT'];
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = ['not a valid JWT'];
|
||||
|
||||
$actual = $this->auth->authenticate($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->auth->authenticate($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testRefreshToken() {
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
public function testRefreshToken() {
|
||||
$data = new stdClass();
|
||||
$data->username = 'admin';
|
||||
$data->password = 'admin';
|
||||
$data->remember = false;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
Auth::CreateJwtSigningKey();
|
||||
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$actual = $this->auth->login($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
|
||||
$jwt = $actual->data[0];
|
||||
$jwt = $actual->data[0];
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [$jwt];
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [$jwt];
|
||||
|
||||
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
|
||||
$user = R::load('user', 1);
|
||||
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
|
||||
$user = R::load('user', 1);
|
||||
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals($user->active_token, $actual->data[0]);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals($user->active_token, $actual->data[0]);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request->hasHeader = false;
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request->hasHeader = false;
|
||||
|
||||
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = ['not a valid JWT'];
|
||||
$this->auth = new Auth(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = ['not a valid JWT'];
|
||||
|
||||
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->auth->refreshToken($request, new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,197 +3,197 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class AutoActionsTest extends PHPUnit\Framework\TestCase {
|
||||
private $actions;
|
||||
private $actions;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
}
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetAllActions() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testGetAllActions() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('No automatic actions in database.',
|
||||
$actual->alerts[0]['text']);
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('No automatic actions in database.',
|
||||
$actual->alerts[0]['text']);
|
||||
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
$this->createAutoAction();
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
$this->createAutoAction();
|
||||
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(1, count($actual->data[1]));
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(1, count($actual->data[1]));
|
||||
$this->assertEquals('success', $actual->status);
|
||||
|
||||
DataMock::CreateStandardUser();
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
DataMock::CreateStandardUser();
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(0, count($actual->data[1]));
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(0, count($actual->data[1]));
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testGetAllActionsUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testGetAllActionsUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->actions->getAllActions($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddAction() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
public function testAddAction() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
|
||||
$data = $this->getDefaultAction();
|
||||
$data = $this->getDefaultAction();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->alerts[0]['type']);
|
||||
}
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testAddActionUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testAddActionUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddActionInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testAddActionInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock, null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock, null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddActionForbidden() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
public function testAddActionForbidden() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$data = $this->getDefaultAction();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$data = $this->getDefaultAction();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->actions->addAction($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveAction() {
|
||||
$this->createAutoAction();
|
||||
public function testRemoveAction() {
|
||||
$this->createAutoAction();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Automatic action removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Automatic action removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveActionForbidden() {
|
||||
$this->createAutoAction();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testRemoveActionForbidden() {
|
||||
$this->createAutoAction();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
$this->actions = new AutoActions(new ContainerMock());
|
||||
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveActionUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$this->createAutoAction();
|
||||
public function testRemoveActionUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$this->createAutoAction();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemovedActionInvalid() {
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such action
|
||||
public function testRemovedActionInvalid() {
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such action
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->actions->removeAction($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
private function getDefaultAction() {
|
||||
$data = new stdClass();
|
||||
$data->board_id = 1;
|
||||
$data->trigger = ActionTrigger::ADDED_TO_CATEGORY;
|
||||
$data->source_id = 1;
|
||||
$data->type = ActionType::CLEAR_DUE_DATE;
|
||||
$data->change_to = 'null';
|
||||
private function getDefaultAction() {
|
||||
$data = new stdClass();
|
||||
$data->board_id = 1;
|
||||
$data->trigger = ActionTrigger::ADDED_TO_CATEGORY;
|
||||
$data->source_id = 1;
|
||||
$data->type = ActionType::CLEAR_DUE_DATE;
|
||||
$data->change_to = 'null';
|
||||
|
||||
return $data;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function createAutoAction() {
|
||||
$auto_action = R::dispense('autoaction');
|
||||
$auto_action->trigger = ActionTrigger::ADDED_TO_CATEGORY;
|
||||
$auto_action->source_id = 1;
|
||||
$auto_action->type = ActionType::CLEAR_DUE_DATE;
|
||||
$auto_action->change_to = 'null';
|
||||
private function createAutoAction() {
|
||||
$auto_action = R::dispense('autoaction');
|
||||
$auto_action->trigger = ActionTrigger::ADDED_TO_CATEGORY;
|
||||
$auto_action->source_id = 1;
|
||||
$auto_action->type = ActionType::CLEAR_DUE_DATE;
|
||||
$auto_action->change_to = 'null';
|
||||
|
||||
$board = R::dispense('board');
|
||||
$board->xownAutoActionList[] = $auto_action;
|
||||
R::store($board);
|
||||
}
|
||||
$board = R::dispense('board');
|
||||
$board->xownAutoActionList[] = $auto_action;
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,370 +3,373 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class BoardsTest extends PHPUnit\Framework\TestCase {
|
||||
private $boards;
|
||||
private $boards;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->boards = new Boards(new ContainerMock());
|
||||
}
|
||||
$this->boards = new Boards(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetAllBoards() {
|
||||
$this->createBoard();
|
||||
public function testGetAllBoards() {
|
||||
$this->createBoard();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$boards = $this->boards->getAllBoards($request,
|
||||
new ResponseMock, null);
|
||||
$this->assertEquals(2, count($boards->data));
|
||||
$this->assertEquals('success', $boards->status);
|
||||
}
|
||||
$boards = $this->boards->getAllBoards($request,
|
||||
new ResponseMock, null);
|
||||
$this->assertEquals(2, count($boards->data));
|
||||
$this->assertEquals('success', $boards->status);
|
||||
}
|
||||
|
||||
public function testGetAllBoardsNotFound() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testGetAllBoardsNotFound() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->boards->getAllBoards($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('No boards in database.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->getAllBoards($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('No boards in database.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetAllBoardsUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testGetAllBoardsUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->getAllBoards($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->getAllBoards($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetBoard() {
|
||||
$this->createBoard();
|
||||
public function testGetBoard() {
|
||||
$this->createBoard();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
|
||||
public function testGetBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testGetBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetBoardNotFound() {
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
public function testGetBoardNotFound() {
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No board found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No board found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetBoardForbidden() {
|
||||
$this->createBoard();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testGetBoardForbidden() {
|
||||
$this->createBoard();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->getBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddBoard() {
|
||||
$data = $this->getBoardData();
|
||||
public function testAddBoard() {
|
||||
$data = $this->getBoardData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->boards->addBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$actual = $this->boards->addBoard($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('Board test added.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$this->assertEquals('Board test added.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testAddBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->addBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->addBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddBoardInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
public function testAddBoardInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$response = $this->boards->addBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$response = $this->boards->addBoard($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateBoard() {
|
||||
$board = $this->getBoardUpdateData();
|
||||
public function testUpdateBoard() {
|
||||
$board = $this->getBoardUpdateData();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $board->id;
|
||||
$args = [];
|
||||
$args['id'] = $board->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $board;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $board;
|
||||
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testUpdateBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateBoardInvalid() {
|
||||
$this->createBoard();
|
||||
public function testUpdateBoardInvalid() {
|
||||
$this->createBoard();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateBoardColumn() {
|
||||
$board = $this->getBoardUpdateData();
|
||||
$board->columns[0]->name = 'changed';
|
||||
public function testUpdateBoardColumn() {
|
||||
$board = $this->getBoardUpdateData();
|
||||
$board->columns[0]->name = 'changed';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $board->id;
|
||||
$args = [];
|
||||
$args['id'] = $board->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $board;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $board;
|
||||
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$cols = $response->data[1][0]['ownColumn'];
|
||||
$this->assertEquals('success', $response->status);
|
||||
$this->assertEquals('changed', $cols[0]['name']);
|
||||
}
|
||||
|
||||
public function testUpdateBoardNotFound() {
|
||||
$this->createBoard();
|
||||
$cols = $response->data[1][0]['ownColumn'];
|
||||
$this->assertEquals('success', $response->status);
|
||||
$this->assertEquals('changed', $cols[0]['name']);
|
||||
}
|
||||
|
||||
public function testUpdateBoardNotFound() {
|
||||
$this->createBoard();
|
||||
|
||||
$board = $this->getBoardData();
|
||||
$board->id = 3;
|
||||
unset($board->columns[0]->board_id);
|
||||
unset($board->categories[0]->board_id);
|
||||
unset($board->issue_trackers[0]->board_id);
|
||||
$board = $this->getBoardData();
|
||||
$board->id = 3;
|
||||
unset($board->columns[0]->board_id);
|
||||
unset($board->categories[0]->board_id);
|
||||
unset($board->issue_trackers[0]->board_id);
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $board->id;
|
||||
$args = [];
|
||||
$args['id'] = $board->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $board;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $board;
|
||||
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$response = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateBoardForbidden() {
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
public function testUpdateBoardForbidden() {
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
public function testRemoveBoard() {
|
||||
$this->createBoard();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
R::store($action);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->boards->removeBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Board test removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
public function testRemoveBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->removeBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveBoardInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1; // No such board
|
||||
|
||||
$this->boards = new Boards(new ContainerMock());
|
||||
|
||||
$response = $this->boards->removeBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
private function getBoardUpdateData() {
|
||||
$this->createBoard();
|
||||
$existing = R::load('board', 1);
|
||||
|
||||
$column = R::dispense('column');
|
||||
$column->name = 'one';
|
||||
$column->position = 1;
|
||||
$existing->xownColumnList[] = $column;
|
||||
$column = R::dispense('column');
|
||||
$column->name = 'two';
|
||||
$column->position = 2;
|
||||
$existing->xownColumnList[] = $column;
|
||||
$category = R::dispense('category');
|
||||
$existing->xownCategoryList[] = $category;
|
||||
R::store($existing);
|
||||
|
||||
$user = R::dispense('user');
|
||||
$user->username = 'test';
|
||||
R::store($user);
|
||||
|
||||
$board = $this->getBoardData();
|
||||
$board->id = 1;
|
||||
|
||||
$newColumn = new stdClass();
|
||||
$newColumn->name = 'col1';
|
||||
$newColumn->position = 0;
|
||||
|
||||
$board->columns[] = $newColumn;
|
||||
$board->users[] = $user->export();
|
||||
|
||||
$board->issue_trackers[0]->board_id = 1;
|
||||
$board->categories = [];
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
private function getBoardData() {
|
||||
$board = new stdClass();
|
||||
$tracker = new stdClass();
|
||||
$category = new stdClass();
|
||||
$column = new stdClass();
|
||||
|
||||
$column->name = 'col2';
|
||||
$column->position = 1;
|
||||
$column->id = 1;
|
||||
$column->board_id = 1;
|
||||
|
||||
$category->name = 'cat 1';
|
||||
$category->default_task_color = '';
|
||||
$category->board_id = 1;
|
||||
|
||||
$tracker->url = 'testing';
|
||||
$tracker->regex = '';
|
||||
$tracker->board_id = 1;
|
||||
$actual = $this->boards->updateBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$board->name = 'test';
|
||||
$board->is_active = true;
|
||||
$board->sharedUserList[] = R::load('user', 1);
|
||||
|
||||
$board->issue_trackers[] = $tracker;
|
||||
$board->categories[] = $category;
|
||||
$board->columns[] = $column;
|
||||
$board->users = [];
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
private function createBoard() {
|
||||
$board = R::dispense('board');
|
||||
$column = R::dispense('column');
|
||||
$task = R::dispense('task');
|
||||
|
||||
$task->sharedUserList[] = R::load('user', 1);
|
||||
|
||||
$column->name = 'test';
|
||||
$column->position = 0;
|
||||
$column->xownTaskList[] = $task;
|
||||
|
||||
$board->name = 'test';
|
||||
$board->is_active = true;
|
||||
$board->sharedUserList[] = R::load('user', 1);
|
||||
$board->xownColumnList[] = $column;
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
public function testRemoveBoard() {
|
||||
$this->createBoard();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
R::store($action);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->boards->removeBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Board test removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveBoardUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->boards->removeBoard($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveBoardInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1; // No such board
|
||||
|
||||
$this->boards = new Boards(new ContainerMock());
|
||||
|
||||
$response = $this->boards->removeBoard($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
private function getBoardUpdateData() {
|
||||
$this->createBoard();
|
||||
$existing = R::load('board', 1);
|
||||
|
||||
$column = R::dispense('column');
|
||||
$column->name = 'one';
|
||||
$column->position = 1;
|
||||
$existing->xownColumnList[] = $column;
|
||||
$column = R::dispense('column');
|
||||
$column->name = 'two';
|
||||
$column->position = 2;
|
||||
$existing->xownColumnList[] = $column;
|
||||
$category = R::dispense('category');
|
||||
$existing->xownCategoryList[] = $category;
|
||||
R::store($existing);
|
||||
|
||||
$user = R::dispense('user');
|
||||
$user->username = 'test';
|
||||
R::store($user);
|
||||
|
||||
$board = $this->getBoardData();
|
||||
$board->id = 1;
|
||||
|
||||
$newColumn = new stdClass();
|
||||
$newColumn->name = 'col1';
|
||||
$newColumn->position = 0;
|
||||
|
||||
$board->columns[] = $newColumn;
|
||||
$board->users[] = $user->export();
|
||||
|
||||
$board->issue_trackers[0]->board_id = 1;
|
||||
$board->categories = [];
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
private function getBoardData() {
|
||||
$board = new stdClass();
|
||||
$tracker = new stdClass();
|
||||
$category = new stdClass();
|
||||
$column = new stdClass();
|
||||
|
||||
$column->name = 'col2';
|
||||
$column->position = 1;
|
||||
$column->id = 1;
|
||||
$column->board_id = 1;
|
||||
|
||||
$category->name = 'cat 1';
|
||||
$category->default_task_color = '';
|
||||
$category->board_id = 1;
|
||||
|
||||
$tracker->url = 'testing';
|
||||
$tracker->regex = '';
|
||||
$tracker->board_id = 1;
|
||||
|
||||
$board->name = 'test';
|
||||
$board->is_active = true;
|
||||
$board->sharedUserList[] = R::load('user', 1);
|
||||
|
||||
$board->issue_trackers[] = $tracker;
|
||||
$board->categories[] = $category;
|
||||
$board->columns[] = $column;
|
||||
$board->users = [];
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
private function createBoard() {
|
||||
$board = R::dispense('board');
|
||||
$column = R::dispense('column');
|
||||
$task = R::dispense('task');
|
||||
|
||||
$task->sharedUserList[] = R::load('user', 1);
|
||||
|
||||
$column->name = 'test';
|
||||
$column->position = 0;
|
||||
$column->xownTaskList[] = $task;
|
||||
|
||||
$board->name = 'test';
|
||||
$board->is_active = true;
|
||||
$board->sharedUserList[] = R::load('user', 1);
|
||||
$board->xownColumnList[] = $column;
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,272 +3,279 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class ColumnsTest extends PHPUnit\Framework\TestCase {
|
||||
private $columns;
|
||||
private $columns;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->columns = new Columns(new ContainerMock());
|
||||
}
|
||||
$this->columns = new Columns(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetColumn() {
|
||||
$this->createColumn();
|
||||
public function testGetColumn() {
|
||||
$this->createColumn();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
|
||||
public function testGetColumnNotFound() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testGetColumnNotFound() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testGetColumnUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testGetColumnUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testGetColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->columns->getColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddColumn() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
public function testAddColumn() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
|
||||
$this->createColumn();
|
||||
$data = $this->getColumnData();
|
||||
$this->createColumn();
|
||||
$data = $this->getColumnData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$actual = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddColumnUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testAddColumnUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddColumnInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
public function testAddColumnInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$response = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$response = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testAddColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testAddColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$column = $this->getColumnData();
|
||||
$column->id = 0;
|
||||
$column = $this->getColumnData();
|
||||
$column->id = 0;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $column;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $column;
|
||||
|
||||
$actual = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->columns->addColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateColumn() {
|
||||
$this->createColumn();
|
||||
public function testUpdateColumn() {
|
||||
$this->createColumn();
|
||||
|
||||
$column = $this->getColumnData();
|
||||
$column->id = 1;
|
||||
$column->name = 'updated';
|
||||
$column = $this->getColumnData();
|
||||
$column->id = 1;
|
||||
$column->name = 'updated';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $column->id;
|
||||
$args = [];
|
||||
$args['id'] = $column->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $column;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $column;
|
||||
|
||||
$response = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
$response = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateColumnUnprivileged() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testUpdateColumnUnprivileged() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testUpdateColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$column = $this->getColumnData();
|
||||
$column->id = 1;
|
||||
$column->name = 'test';
|
||||
$column = $this->getColumnData();
|
||||
$column->id = 1;
|
||||
$column->name = 'test';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $column->id;
|
||||
$args = [];
|
||||
$args['id'] = $column->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $column;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $column;
|
||||
|
||||
$this->columns = new Columns(new ContainerMock());
|
||||
$this->columns = new Columns(new ContainerMock());
|
||||
|
||||
$actual = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateColumnInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
public function testUpdateColumnInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$response = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
public function testRemoveColumn() {
|
||||
$this->createColumn();
|
||||
$response = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$response = $this->columns->updateColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testRemoveColumn() {
|
||||
$this->createColumn();
|
||||
|
||||
$actual = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
public function testRemoveColumnUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$actual = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
$actual = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
public function testRemoveColumnUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
public function testRemoveColumnInvalid() {
|
||||
$args = [];
|
||||
$args['id'] = 1; // No such column
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$actual = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$response = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
public function testRemoveColumnInvalid() {
|
||||
$args = [];
|
||||
$args['id'] = 1; // No such column
|
||||
|
||||
public function testRemoveColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$response = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
public function testRemoveColumnForbidden() {
|
||||
$this->createColumn();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$actual = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
private function getColumnData() {
|
||||
$data = new stdClass();
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$data->name = 'test';
|
||||
$data->position = 0;
|
||||
$data->board_id = 1;
|
||||
$data->tasks = [];
|
||||
$actual = $this->columns->removeColumn($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
private function getColumnData() {
|
||||
$data = new stdClass();
|
||||
|
||||
private function createColumn() {
|
||||
$column = R::dispense('column');
|
||||
$data->name = 'test';
|
||||
$data->position = 0;
|
||||
$data->board_id = 1;
|
||||
$data->tasks = [];
|
||||
|
||||
$board = R::dispense('board');
|
||||
$board->xownColumnList[] = $column;
|
||||
return $data;
|
||||
}
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
private function createColumn() {
|
||||
$column = R::dispense('column');
|
||||
|
||||
$board = R::dispense('board');
|
||||
$board->xownColumnList[] = $column;
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,313 +3,320 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class CommentsTest extends PHPUnit\Framework\TestCase {
|
||||
private $comments;
|
||||
private $comments;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->comments = new Comments(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetComment() {
|
||||
$this->createComment();
|
||||
$this->comments = new Comments(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetComment() {
|
||||
$this->createComment();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
|
||||
public function testGetCommentNotFound() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No comment found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
public function testGetCommentNotFound() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$this->comments = new Comments(new ContainerMock());
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddComment() {
|
||||
$this->createComment();
|
||||
$data = $this->getCommentData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$comment = $this->getCommentData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $comment;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddCommentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testAddCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::createBoardAdminUser();
|
||||
$comment = $this->getCommentData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $comment;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateComment() {
|
||||
$this->createComment();
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No comment found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$comment = $this->getCommentData();
|
||||
$comment->id = 1;
|
||||
$comment->text = 'updated';
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$this->comments = new Comments(new ContainerMock());
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = $comment->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $comment;
|
||||
|
||||
$response = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testGetCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->comments->getComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddComment() {
|
||||
$this->createComment();
|
||||
$data = $this->getCommentData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$comment = $this->getCommentData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $comment;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddCommentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testUpdateCommentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$response = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
|
||||
$response = $this->comments->updateComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->comments->updateComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::createBoardAdminUser();
|
||||
|
||||
public function testAddCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::createBoardAdminUser();
|
||||
$comment = $this->getCommentData();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $comment;
|
||||
|
||||
$actual = $this->comments->addComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateComment() {
|
||||
$this->createComment();
|
||||
|
||||
$comment = $this->getCommentData();
|
||||
$comment->id = 1;
|
||||
$comment->text = 'updated';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $comment->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $comment;
|
||||
|
||||
$response = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateCommentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
$comment = $this->getCommentData();
|
||||
$comment->id = 1;
|
||||
$comment->text = 'updated';
|
||||
|
||||
$response = $this->comments->updateComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->comments->updateComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::createBoardAdminUser();
|
||||
$args = [];
|
||||
$args['id'] = $comment->id;
|
||||
|
||||
$comment = $this->getCommentData();
|
||||
$comment->id = 1;
|
||||
$comment->text = 'updated';
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $comment;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $comment->id;
|
||||
$actual = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $comment;
|
||||
public function testUpdateCommentUserSecurity() {
|
||||
$this->createComment();
|
||||
DataMock::CreateStandardUser();
|
||||
|
||||
$actual = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
public function testUpdateCommentUserSecurity() {
|
||||
$this->createComment();
|
||||
DataMock::CreateStandardUser();
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$actual = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$this->assertEquals('You do not have sufficient permissions to ' .
|
||||
'update this comment.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$actual = $this->comments->updateComment($request,
|
||||
new ResponseMock(), $args);
|
||||
public function testRemoveComment() {
|
||||
$this->createComment();
|
||||
|
||||
$this->assertEquals('You do not have sufficient permissions to ' .
|
||||
'update this comment.', $actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
public function testRemoveComment() {
|
||||
$this->createComment();
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testRemoveCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
public function testRemoveCommentUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
public function testRemoveCommentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1; // No such comment
|
||||
|
||||
public function testRemoveCommentInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$response = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1; // No such comment
|
||||
public function testRemoveCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$response = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
public function testRemoveCommentForbidden() {
|
||||
$this->createComment();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
public function testRemoveCommentUserSecurity() {
|
||||
$this->createComment();
|
||||
DataMock::CreateStandardUser();
|
||||
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
public function testRemoveCommentUserSecurity() {
|
||||
$this->createComment();
|
||||
DataMock::CreateStandardUser();
|
||||
$this->comments = new Comments(new ContainerMock());
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$this->comments = new Comments(new ContainerMock());
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$this->assertEquals('You do not have sufficient permissions to ' .
|
||||
'remove this comment.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
$actual = $this->comments->removeComment($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('You do not have sufficient permissions to ' .
|
||||
'remove this comment.', $actual->alerts[0]['text']);
|
||||
}
|
||||
private function getCommentData() {
|
||||
$data = new stdClass();
|
||||
|
||||
$data->text = 'test comment';
|
||||
$data->user_id = 1;
|
||||
$data->task_id = 1;
|
||||
$data->timestamp = time();
|
||||
|
||||
private function getCommentData() {
|
||||
$data = new stdClass();
|
||||
return $data;
|
||||
}
|
||||
|
||||
$data->text = 'test comment';
|
||||
$data->user_id = 1;
|
||||
$data->task_id = 1;
|
||||
$data->timestamp = time();
|
||||
private function createComment() {
|
||||
$comment = R::dispense('comment');
|
||||
R::store($comment);
|
||||
|
||||
return $data;
|
||||
}
|
||||
$task = R::dispense('task');
|
||||
$task->xownCommentList[] = $comment;
|
||||
|
||||
private function createComment() {
|
||||
$comment = R::dispense('comment');
|
||||
R::store($comment);
|
||||
$column = R::dispense('column');
|
||||
$column->xownTaskList[] = $task;
|
||||
|
||||
$task = R::dispense('task');
|
||||
$task->xownCommentList[] = $comment;
|
||||
$admin = R::load('user', 1);
|
||||
$board = R::dispense('board');
|
||||
$board->xownColumnList[] = $column;
|
||||
$board->sharedUserList[] = $admin;
|
||||
|
||||
$column = R::dispense('column');
|
||||
$column->xownTaskList[] = $task;
|
||||
|
||||
$admin = R::load('user', 1);
|
||||
$board = R::dispense('board');
|
||||
$board->xownColumnList[] = $column;
|
||||
$board->sharedUserList[] = $admin;
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
R::store($board);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,436 +3,443 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class TasksTest extends PHPUnit\Framework\TestCase {
|
||||
private $tasks;
|
||||
private $tasks;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->tasks = new Tasks(new ContainerMock());
|
||||
}
|
||||
$this->tasks = new Tasks(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetTask() {
|
||||
$this->createTask();
|
||||
public function testGetTask() {
|
||||
$this->createTask();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
|
||||
public function testGetTaskNotFound() {
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
public function testGetTaskNotFound() {
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), $args);
|
||||
$this->assertEquals('No task found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), $args);
|
||||
$this->assertEquals('No task found for ID 1.',
|
||||
$actual->alerts[0]['text']);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
public function testGetTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testGetTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->tasks->getTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddTask() {
|
||||
$this->createTask();
|
||||
$data = $this->getTaskData();
|
||||
public function testAddTask() {
|
||||
$this->createTask();
|
||||
$data = $this->getTaskData();
|
||||
|
||||
$assignee = R::load('user', 1);
|
||||
$data->assignees[] = $assignee;
|
||||
$assignee = R::load('user', 1);
|
||||
$data->assignees[] = $assignee;
|
||||
|
||||
$category = R::load('category', 1);
|
||||
$category->name = 'Front End';
|
||||
R::store($category);
|
||||
$data->categories[] = $category;
|
||||
$category = R::load('category', 1);
|
||||
$category->name = 'Front End';
|
||||
R::store($category);
|
||||
$data->categories[] = $category;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddTaskTop() {
|
||||
$this->createTask();
|
||||
$data = $this->getTaskData();
|
||||
public function testAddTaskTop() {
|
||||
$this->createTask();
|
||||
$data = $this->getTaskData();
|
||||
|
||||
$user = R::load('user', 1);
|
||||
$opts = R::load('useroption', $user->user_option_id);
|
||||
$user = R::load('user', 1);
|
||||
$opts = R::load('useroption', $user->user_option_id);
|
||||
|
||||
$opts->new_tasks_at_bottom = false;
|
||||
R::store($opts);
|
||||
$opts->new_tasks_at_bottom = false;
|
||||
R::store($opts);
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $data;
|
||||
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testAddTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request= new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request= new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddTaskInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$response = $this->tasks->addTask($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
public function testAddTaskInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
public function testAddTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
$response = $this->tasks->addTask($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 0;
|
||||
public function testAddTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request->payload = $task;
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 0;
|
||||
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateTask() {
|
||||
$this->createTask();
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 1;
|
||||
$task->title = 'updated';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $task->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->payload = $task;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
$this->assertEquals('updated', $response->data[1][0]['title']);
|
||||
}
|
||||
|
||||
public function testUpdateTaskWithActions() {
|
||||
$this->addActions();
|
||||
$this->createTask();
|
||||
|
||||
DataMock::CreateStandardUser();
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 1;
|
||||
$task->column_id = 2;
|
||||
$task->title = 'updated';
|
||||
$task->assignees = [];
|
||||
$task->assignees[] = R::load('user', 2);
|
||||
$task->categories = [];
|
||||
$task->categories[] = R::load('category', 2);
|
||||
$task->points = 5;
|
||||
$task->due_date = '1/1/2017';
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request->payload = $task;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $task->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->payload = $task;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
|
||||
$updated = $response->data[1][0];
|
||||
$this->assertEquals('updated', $updated['title']);
|
||||
$this->assertEquals('#cdcdcd', $updated['color']);
|
||||
$this->assertEquals(2, (int)$updated['sharedUser'][0]['id']);
|
||||
$this->assertEquals('', $updated['due_date']);
|
||||
|
||||
$temp = R::load('task', 1);
|
||||
$temp->due_date = '';
|
||||
R::store($temp);
|
||||
|
||||
$task->column_id = 1;
|
||||
$task->due_date ='';
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->payload = $task;
|
||||
$actual = $this->tasks->addTask($request, new ResponseMock(), null);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateTask() {
|
||||
$this->createTask();
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 1;
|
||||
$task->title = 'updated';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $task->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->payload = $task;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
$this->assertEquals('updated', $response->data[1][0]['title']);
|
||||
}
|
||||
|
||||
public function testUpdateTaskWithActions() {
|
||||
$this->addActions();
|
||||
$this->createTask();
|
||||
|
||||
DataMock::CreateStandardUser();
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 1;
|
||||
$task->column_id = 2;
|
||||
$task->title = 'updated';
|
||||
$task->assignees = [];
|
||||
$task->assignees[] = R::load('user', 2);
|
||||
$task->categories = [];
|
||||
$task->categories[] = R::load('category', 2);
|
||||
$task->points = 5;
|
||||
$task->due_date = '1/1/2017';
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateTaskInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 1;
|
||||
$task->title = 'updated';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $task->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request->payload = $task;
|
||||
|
||||
$actual = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveTask() {
|
||||
$this->createTask();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$actual = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('Task test removed.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveTaskInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such task
|
||||
|
||||
$response = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testRemoveTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
private function addActions() {
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 1; // Moved to column
|
||||
$action->source_id = 2; // Column ID
|
||||
$action->type = 1; // Set color
|
||||
$action->change_to = '#fff';
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 2; // Assigned to user
|
||||
$action->source_id = 2; // User ID
|
||||
$action->type = 2; // Set category
|
||||
$action->change_to = 2; // Category ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 2; // Assigned to user
|
||||
$action->source_id = 2; // User ID
|
||||
$action->type = 3; // Add category
|
||||
$action->change_to = 0; // Category ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 3; // Assigned to category
|
||||
$action->source_id = 2; // Category ID
|
||||
$action->type = 4; // Set assignee
|
||||
$action->change_to = 1; // User ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 3; // Assigned to category
|
||||
$action->source_id = 2; // Category ID
|
||||
$action->type = 5; // Add assignee
|
||||
$action->change_to = 0; // User ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 3; // Assigned to category
|
||||
$action->source_id = 2; // Category ID
|
||||
$action->type = 6; // Clear due date
|
||||
$action->change_to = 0;
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 1; // Moved to column
|
||||
$action->source_id = 1; // Category ID
|
||||
$action->type = 6; // Clear due date
|
||||
$action->change_to = 0;
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 4; // Points changed
|
||||
$action->source_id = 0;
|
||||
$action->type = 7; // Alter color by points
|
||||
$action->change_to = 0;
|
||||
|
||||
R::store($action);
|
||||
}
|
||||
|
||||
private function getTaskData() {
|
||||
$data = new stdClass();
|
||||
|
||||
$data->title = 'task';
|
||||
$data->description = 'the words';
|
||||
$data->column_id = 1;
|
||||
$data->color = '';
|
||||
$data->due_date = null;
|
||||
$data->points = null;
|
||||
$data->position = 0;
|
||||
$data->comments = [];
|
||||
$data->attachments = [];
|
||||
$data->assignees = [];
|
||||
$data->categories = [];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function createTask() {
|
||||
$user = R::load('user', 1);
|
||||
|
||||
$task = R::dispense('task');
|
||||
$task->title = 'test';
|
||||
$task->sharedUserList[] = $user;
|
||||
|
||||
$column = R::dispense('column');
|
||||
$column->xownTaskList[] = $task;
|
||||
$column2 = R::dispense('column');
|
||||
|
||||
$category = R::dispense('category');
|
||||
$category2 = R::dispense('category');
|
||||
|
||||
$board = R::dispense('board');
|
||||
$board->xownColumnList[] = $column;
|
||||
$board->xownColumnList[] = $column2;
|
||||
$board->xownCategoryList[] = $category;
|
||||
$board->xownCategoryList[] = $category2;
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
$args = [];
|
||||
$args['id'] = $task->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->payload = $task;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
|
||||
$updated = $response->data[1][0];
|
||||
$this->assertEquals('updated', $updated['title']);
|
||||
$this->assertEquals('#cdcdcd', $updated['color']);
|
||||
$this->assertEquals(2, (int)$updated['sharedUser'][0]['id']);
|
||||
$this->assertEquals('', $updated['due_date']);
|
||||
|
||||
$temp = R::load('task', 1);
|
||||
$temp->due_date = '';
|
||||
R::store($temp);
|
||||
|
||||
$task->column_id = 1;
|
||||
$task->due_date ='';
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->payload = $task;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateTaskInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
|
||||
$response = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$task = $this->getTaskData();
|
||||
$task->id = 1;
|
||||
$task->title = 'updated';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $task->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
$request->payload = $task;
|
||||
|
||||
$actual = $this->tasks->updateTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveTask() {
|
||||
$this->createTask();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$actual = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('Task test removed.', $actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveTaskUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$actual = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveTaskInvalid() {
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt()];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such task
|
||||
|
||||
$response = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testRemoveTaskForbidden() {
|
||||
$this->createTask();
|
||||
DataMock::CreateBoardAdminUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::getJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->tasks->removeTask($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
private function addActions() {
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 1; // Moved to column
|
||||
$action->source_id = 2; // Column ID
|
||||
$action->type = 1; // Set color
|
||||
$action->change_to = '#fff';
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 2; // Assigned to user
|
||||
$action->source_id = 2; // User ID
|
||||
$action->type = 2; // Set category
|
||||
$action->change_to = 2; // Category ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 2; // Assigned to user
|
||||
$action->source_id = 2; // User ID
|
||||
$action->type = 3; // Add category
|
||||
$action->change_to = 0; // Category ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 3; // Assigned to category
|
||||
$action->source_id = 2; // Category ID
|
||||
$action->type = 4; // Set assignee
|
||||
$action->change_to = 1; // User ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 3; // Assigned to category
|
||||
$action->source_id = 2; // Category ID
|
||||
$action->type = 5; // Add assignee
|
||||
$action->change_to = 0; // User ID
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 3; // Assigned to category
|
||||
$action->source_id = 2; // Category ID
|
||||
$action->type = 6; // Clear due date
|
||||
$action->change_to = 0;
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 1; // Moved to column
|
||||
$action->source_id = 1; // Category ID
|
||||
$action->type = 6; // Clear due date
|
||||
$action->change_to = 0;
|
||||
|
||||
R::store($action);
|
||||
|
||||
$action = R::dispense('autoaction');
|
||||
$action->board_id = 1;
|
||||
$action->trigger = 4; // Points changed
|
||||
$action->source_id = 0;
|
||||
$action->type = 7; // Alter color by points
|
||||
$action->change_to = 0;
|
||||
|
||||
R::store($action);
|
||||
}
|
||||
|
||||
private function getTaskData() {
|
||||
$data = new stdClass();
|
||||
|
||||
$data->title = 'task';
|
||||
$data->description = 'the words';
|
||||
$data->column_id = 1;
|
||||
$data->color = '';
|
||||
$data->due_date = null;
|
||||
$data->points = null;
|
||||
$data->position = 0;
|
||||
$data->comments = [];
|
||||
$data->attachments = [];
|
||||
$data->assignees = [];
|
||||
$data->categories = [];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function createTask() {
|
||||
$user = R::load('user', 1);
|
||||
|
||||
$task = R::dispense('task');
|
||||
$task->title = 'test';
|
||||
$task->sharedUserList[] = $user;
|
||||
|
||||
$column = R::dispense('column');
|
||||
$column->xownTaskList[] = $task;
|
||||
$column2 = R::dispense('column');
|
||||
|
||||
$category = R::dispense('category');
|
||||
$category2 = R::dispense('category');
|
||||
|
||||
$board = R::dispense('board');
|
||||
$board->xownColumnList[] = $column;
|
||||
$board->xownColumnList[] = $column2;
|
||||
$board->xownCategoryList[] = $category;
|
||||
$board->xownCategoryList[] = $category2;
|
||||
|
||||
R::store($board);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,546 +3,546 @@ require_once __DIR__ . '/../Mocks.php';
|
||||
use RedBeanPHP\R;
|
||||
|
||||
class UsersTest extends PHPUnit\Framework\TestCase {
|
||||
private $users;
|
||||
private $users;
|
||||
|
||||
public static function setupBeforeClass() {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
public static function setUpBeforeClass(): void {
|
||||
try {
|
||||
R::setup('sqlite:tests.db');
|
||||
} catch (Exception $ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
public function setUp(): void {
|
||||
R::nuke();
|
||||
Auth::CreateInitialAdmin(new ContainerMock());
|
||||
|
||||
$this->users = new Users(new ContainerMock());
|
||||
}
|
||||
$this->users = new Users(new ContainerMock());
|
||||
}
|
||||
|
||||
public function testGetAllUsers() {
|
||||
$this->createUser();
|
||||
public function testGetAllUsers() {
|
||||
$this->createUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->users->getAllUsers($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(2, count($actual->data[1]));
|
||||
$actual = $this->users->getAllUsers($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals(2, count($actual->data[1]));
|
||||
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$this->users = new Users(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(3)];
|
||||
$this->users = new Users(new ContainerMock());
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(3)];
|
||||
|
||||
$actual = $this->users->getAllUsers($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->getAllUsers($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('error', $actual->alerts[0]['type']);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetUser() {
|
||||
$this->createUser();
|
||||
public function testGetUser() {
|
||||
$this->createUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
$this->assertEquals('success', $actual->status);
|
||||
$this->assertEquals(2, count($actual->data));
|
||||
}
|
||||
|
||||
public function testGetUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testGetUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetUserNotFound() {
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
public function testGetUserNotFound() {
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No user found for ID 2.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('No user found for ID 2.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testGetUserForbidden() {
|
||||
$this->createUser();
|
||||
DataMock::CreateStandardUser('nono');
|
||||
public function testGetUserForbidden() {
|
||||
$this->createUser();
|
||||
DataMock::CreateStandardUser('nono');
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(3)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(3)];
|
||||
|
||||
$this->users = new Users(new ContainerMock());
|
||||
$this->users = new Users(new ContainerMock());
|
||||
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->getUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddUser() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
public function testAddUser() {
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->default_board_id = $board->id;
|
||||
$user = $this->getUserData();
|
||||
$user->default_board_id = $board->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $user;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $user;
|
||||
|
||||
$actual = $this->users->addUser($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
$actual = $this->users->addUser($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('success', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddDuplicateUser() {
|
||||
$user = $this->getUserData();
|
||||
$user->username = 'admin';
|
||||
public function testAddDuplicateUser() {
|
||||
$user = $this->getUserData();
|
||||
$user->username = 'admin';
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $user;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $user;
|
||||
|
||||
$actual = $this->users->addUser($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->users->addUser($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testAddUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testAddUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$actual = $this->users->addUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->addUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testAddBadUser() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
public function testAddBadUser() {
|
||||
$request = new RequestMock();
|
||||
$request->invalidPayload = true;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$response = $this->users->addUser($request,
|
||||
new ResponseMock(), null);
|
||||
$response = $this->users->addUser($request,
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateUser() {
|
||||
$this->createUser();
|
||||
public function testUpdateUser() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'newname';
|
||||
$user->default_board_id = 1;
|
||||
$user->password = 'test';
|
||||
$user->boardAccess = [2];
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'newname';
|
||||
$user->default_board_id = 1;
|
||||
$user->password = 'test';
|
||||
$user->boardAccess = [2];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserRemoveDefaultBoard() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserRemoveDefaultBoard() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->boardAccess = [1];
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->boardAccess = [1];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserPassword() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserPassword() {
|
||||
$this->createUser();
|
||||
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
$board = R::dispense('board');
|
||||
R::store($board);
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->new_password = 'updated';
|
||||
$user->old_password = 'test';
|
||||
$user->default_board_id = 2;
|
||||
$user->boardAccess = [];
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->new_password = 'updated';
|
||||
$user->old_password = 'test';
|
||||
$user->default_board_id = 2;
|
||||
$user->boardAccess = [];
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserBadPassword() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserBadPassword() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->new_password = 'updated';
|
||||
$user->old_password = 'wrong';
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->new_password = 'updated';
|
||||
$user->old_password = 'wrong';
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $user;
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserInvalid() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserInvalid() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'newname';
|
||||
$user->default_board_id = 1;
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'newname';
|
||||
$user->default_board_id = 1;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->invalidPayload = true;
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('error', $response->alerts[0]['type']);
|
||||
}
|
||||
|
||||
public function testUpdateUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testUpdateUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->users->updateUser($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->updateUser($request,
|
||||
new ResponseMock(), null);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateUserRestricted() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserRestricted() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 1;
|
||||
$user = $this->getUserData();
|
||||
$user->id = 1;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $user;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $user;
|
||||
|
||||
$actual = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
$actual = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $actual->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserBadId() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserBadId() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'newname';
|
||||
$user->default_board_id = 1;
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'newname';
|
||||
$user->default_board_id = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $user;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request->payload = $user;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id + 1;
|
||||
$args = [];
|
||||
$args['id'] = $user->id + 1;
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserNameInUse() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserNameInUse() {
|
||||
$this->createUser();
|
||||
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'admin';
|
||||
$user = $this->getUserData();
|
||||
$user->id = 2;
|
||||
$user->username = 'admin';
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $user;
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request->payload = $user;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
$args = [];
|
||||
$args['id'] = $user->id;
|
||||
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserOptions() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserOptions() {
|
||||
$this->createUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$opts = $this->getUserOptionData();
|
||||
$opts->id = 2;
|
||||
$opts->new_tasks_at_bottom = false;
|
||||
$opts = $this->getUserOptionData();
|
||||
$opts->id = 2;
|
||||
$opts->new_tasks_at_bottom = false;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $opts;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $opts;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserOptionsRestricted() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserOptionsRestricted() {
|
||||
$this->createUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
$args = [];
|
||||
$args['id'] = 1;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$this->users = new Users(new ContainerMock());
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->users = new Users(new ContainerMock());
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$response->alerts[0]['text']);
|
||||
}
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('Access restricted.',
|
||||
$response->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testUpdateUserOptionsUnprivileged() {
|
||||
DataMock::createUnprivilegedUser();
|
||||
public function testUpdateUserOptionsUnprivileged() {
|
||||
DataMock::createUnprivilegedUser();
|
||||
|
||||
$data = $this->getUserOptionData();
|
||||
$data->id = 2;
|
||||
$data = $this->getUserOptionData();
|
||||
$data->id = 2;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testUpdateUserOptionsBadId() {
|
||||
$this->createUser();
|
||||
public function testUpdateUserOptionsBadId() {
|
||||
$this->createUser();
|
||||
|
||||
$data = new stdClass();
|
||||
$data->id = 2; // No such user options
|
||||
$data = new stdClass();
|
||||
$data->id = 2; // No such user options
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$response = $this->users->updateUserOptions($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testToggleCollapsed() {
|
||||
$this->createUser();
|
||||
public function testToggleCollapsed() {
|
||||
$this->createUser();
|
||||
|
||||
$data = new stdClass();
|
||||
$data->id = 1;
|
||||
$data = new stdClass();
|
||||
$data->id = 1;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
// Collapse the column
|
||||
$response = $this->users->toggleCollapsed($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
// Collapse the column
|
||||
$response = $this->users->toggleCollapsed($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
|
||||
// Expand the column
|
||||
$response = $this->users->toggleCollapsed($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
// Expand the column
|
||||
$response = $this->users->toggleCollapsed($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('success', $response->status);
|
||||
}
|
||||
|
||||
public function testToggleCollapsedNoAccess() {
|
||||
$response = $this->users->toggleCollapsed(new RequestMock(),
|
||||
new ResponseMock(), null);
|
||||
public function testToggleCollapsedNoAccess() {
|
||||
$response = $this->users->toggleCollapsed(new RequestMock(),
|
||||
new ResponseMock(), null);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
|
||||
$data = new stdClass();
|
||||
$data->id = 1;
|
||||
$data = new stdClass();
|
||||
$data->id = 1;
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(1)];
|
||||
$request = new RequestMock();
|
||||
$request->payload = $data;
|
||||
$request->header = [DataMock::GetJwt(1)];
|
||||
|
||||
$response = $this->users->toggleCollapsed($request,
|
||||
new ResponseMock(), $args);
|
||||
$response = $this->users->toggleCollapsed($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
public function testRemoveUser() {
|
||||
$this->createUser();
|
||||
public function testRemoveUser() {
|
||||
$this->createUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$actual = $this->users->removeUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$actual = $this->users->removeUser($request,
|
||||
new ResponseMock(), $args);
|
||||
|
||||
$this->assertEquals('User tester removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$this->assertEquals('User tester removed.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
public function testRemoveUserUnprivileged() {
|
||||
DataMock::CreateUnprivilegedUser();
|
||||
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
$args = [];
|
||||
$args['id'] = 2;
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt(2)];
|
||||
|
||||
$actual = $this->users->removeUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
$actual = $this->users->removeUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('Insufficient privileges.',
|
||||
$actual->alerts[0]['text']);
|
||||
}
|
||||
|
||||
public function testRemoveBadUser() {
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such user
|
||||
public function testRemoveBadUser() {
|
||||
$args = [];
|
||||
$args['id'] = 2; // No such user
|
||||
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
$request = new RequestMock();
|
||||
$request->header = [DataMock::GetJwt()];
|
||||
|
||||
$response = $this->users->removeUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
$response = $this->users->removeUser($request,
|
||||
new ResponseMock(), $args);
|
||||
$this->assertEquals('failure', $response->status);
|
||||
}
|
||||
|
||||
private function getUserData() {
|
||||
$data = new stdClass();
|
||||
private function getUserData() {
|
||||
$data = new stdClass();
|
||||
|
||||
$data->security_level = SecurityLevel::USER;
|
||||
$data->username = 'tester';
|
||||
$data->email = '';
|
||||
$data->default_board_id = 0;
|
||||
$data->user_option_id = 0;
|
||||
$data->last_login = 0;
|
||||
$data->active_token = '';
|
||||
$data->security_level = SecurityLevel::USER;
|
||||
$data->username = 'tester';
|
||||
$data->email = '';
|
||||
$data->default_board_id = 0;
|
||||
$data->user_option_id = 0;
|
||||
$data->last_login = 0;
|
||||
$data->active_token = '';
|
||||
|
||||
$data->password = 'test';
|
||||
$data->password_verify = 'test';
|
||||
$data->password = 'test';
|
||||
$data->password_verify = 'test';
|
||||
|
||||
return $data;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getUserOptionData() {
|
||||
$data = new stdClass();
|
||||
private function getUserOptionData() {
|
||||
$data = new stdClass();
|
||||
|
||||
$data->new_tasks_at_bottom = true;
|
||||
$data->show_animations = true;
|
||||
$data->show_assignee = true;
|
||||
$data->multiple_tasks_per_row = false;
|
||||
$data->language = "en";
|
||||
$data->new_tasks_at_bottom = true;
|
||||
$data->show_animations = true;
|
||||
$data->show_assignee = true;
|
||||
$data->multiple_tasks_per_row = false;
|
||||
$data->language = "en";
|
||||
|
||||
return $data;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function createUser() {
|
||||
$opts = R::dispense('useroption');
|
||||
R::store($opts);
|
||||
private function createUser() {
|
||||
$opts = R::dispense('useroption');
|
||||
R::store($opts);
|
||||
|
||||
$user = R::dispense('user');
|
||||
$user->security_level = SecurityLevel::USER;
|
||||
$user->username = 'tester';
|
||||
$user->default_board_id = 1;
|
||||
$user->password_hash = password_hash('test', PASSWORD_BCRYPT);
|
||||
$user->user_option_id = $opts->id;
|
||||
$user = R::dispense('user');
|
||||
$user->security_level = SecurityLevel::USER;
|
||||
$user->username = 'tester';
|
||||
$user->default_board_id = 1;
|
||||
$user->password_hash = password_hash('test', PASSWORD_BCRYPT);
|
||||
$user->user_option_id = $opts->id;
|
||||
|
||||
$admin = R::load('user', 1);
|
||||
$board = R::dispense('board');
|
||||
$board->sharedUserList[] = $admin;
|
||||
$board->sharedUserList[] = $user;
|
||||
R::store($board);
|
||||
}
|
||||
$admin = R::load('user', 1);
|
||||
$board = R::dispense('board');
|
||||
$board->sharedUserList[] = $admin;
|
||||
$board->sharedUserList[] = $user;
|
||||
R::store($board);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<phpunit>
|
||||
<testsuites>
|
||||
<testsuite>
|
||||
<testsuite name="api">
|
||||
<directory>./</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
@ -82,7 +82,7 @@ describe('ApiInterceptor', () => {
|
||||
it('handles errors and clears the JWT',
|
||||
inject([HttpClient, HttpTestingController],
|
||||
(http: HttpClient, httpMock: HttpTestingController) => {
|
||||
sessionStorage.setItem('taskboard.jwt', 'fake');
|
||||
sessionStorage.setItem('taskboard.jwt', null);
|
||||
|
||||
http.get('').subscribe(response => {
|
||||
expect(response).toBeTruthy();
|
||||
|
@ -41,180 +41,186 @@ describe('BoardService', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
// it('lets the active board get updated', () => {
|
||||
// let changed = false;
|
||||
//
|
||||
// service.activeBoardChanged.subscribe(() => (changed = true));
|
||||
//
|
||||
// service.updateActiveBoard(<any>{});
|
||||
//
|
||||
// expect(changed).toEqual(true);
|
||||
// });
|
||||
//
|
||||
// it('gets all boards', () => {
|
||||
// service.getBoards().subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/boards', 'GET');
|
||||
// });
|
||||
//
|
||||
// it('handles errors when getting all boards', () => {
|
||||
// service.getBoards().subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/boards', 'GET', true);
|
||||
// });
|
||||
//
|
||||
// it('toggles the collapsed state of a column', () => {
|
||||
// service.toggleCollapsed(1, 1).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/users/1/cols', 'POST');
|
||||
// });
|
||||
//
|
||||
// it('handles error when toggling collapse', () => {
|
||||
// service.toggleCollapsed(1, 1).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/users/1/cols', 'POST', true);
|
||||
// });
|
||||
//
|
||||
// it('updates a board', () => {
|
||||
// service.updateBoard(<any>{ id: 1 }).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/boards/1', 'POST');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on board update', () => {
|
||||
// service.updateBoard(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/boards/1', 'POST', true);
|
||||
// });
|
||||
//
|
||||
// it('updates a column', () => {
|
||||
// service.updateColumn(<any>{ id: 1 }).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/columns/1', 'POST');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on column update', () => {
|
||||
// service.updateColumn(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/columns/1', 'POST', true);
|
||||
// });
|
||||
//
|
||||
// it('adds a task', () => {
|
||||
// service.addTask(<any>{}).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/tasks', 'POST');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on task add', () => {
|
||||
// service.addTask(<any>{}).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/tasks', 'POST', true);
|
||||
// });
|
||||
//
|
||||
// it('updates a task', () => {
|
||||
// service.updateTask(<any>{ id: 1 }).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/tasks/1', 'POST');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on task update', () => {
|
||||
// service.updateTask(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/tasks/1', 'POST', true);
|
||||
// });
|
||||
//
|
||||
// it('removes a task', () => {
|
||||
// service.removeTask(1).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/tasks/1', 'DELETE');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on task removal', () => {
|
||||
// service.removeTask(1).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/tasks/1', 'DELETE', true);
|
||||
// });
|
||||
//
|
||||
// it('gets task activity', () => {
|
||||
// service.getTaskActivity(1).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/activity/task/1', 'GET');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on get task activity', () => {
|
||||
// service.getTaskActivity(1).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/activity/task/1', 'GET', true);
|
||||
// });
|
||||
//
|
||||
// it('updates a comment', () => {
|
||||
// service.updateComment(<any>{ id: 1 }).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/comments/1', 'POST');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on comment update', () => {
|
||||
// service.updateComment(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/comments/1', 'POST', true);
|
||||
// });
|
||||
//
|
||||
// it('removes a comment', () => {
|
||||
// service.removeComment(1).subscribe(response => {
|
||||
// expect(response.data.length).toEqual(0);
|
||||
// });
|
||||
//
|
||||
// testCall('api/comments/1', 'DELETE');
|
||||
// });
|
||||
//
|
||||
// it('handles errors on comment removal', () => {
|
||||
// service.removeComment(1).subscribe(() => {}, response => {
|
||||
// expect(response.alerts.length).toEqual(1);
|
||||
// });
|
||||
//
|
||||
// testCall('api/comments/1', 'DELETE', true);
|
||||
// });
|
||||
//
|
||||
// it('refreshes the API token', () => {
|
||||
// service.refreshToken();
|
||||
// testCall('api/refresh', 'POST');
|
||||
// });
|
||||
it('lets the active board get updated', () => {
|
||||
let changed = false;
|
||||
|
||||
service.activeBoardChanged.subscribe(() => (changed = true));
|
||||
|
||||
service.updateActiveBoard(<any>{});
|
||||
|
||||
expect(changed).toEqual(true);
|
||||
});
|
||||
|
||||
it('gets all boards', () => {
|
||||
service.getBoards().subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/boards', 'GET');
|
||||
});
|
||||
|
||||
it('converts markdown', () => {
|
||||
const actual = service.convertMarkdown('# Test');
|
||||
|
||||
expect(actual.html).toEqual('<h1 id="test">Test</h1>\n');
|
||||
});
|
||||
|
||||
it('handles errors when getting all boards', () => {
|
||||
service.getBoards().subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/boards', 'GET', true);
|
||||
});
|
||||
|
||||
it('toggles the collapsed state of a column', () => {
|
||||
service.toggleCollapsed(1, 1).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/users/1/cols', 'POST');
|
||||
});
|
||||
|
||||
it('handles error when toggling collapse', () => {
|
||||
service.toggleCollapsed(1, 1).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/users/1/cols', 'POST', true);
|
||||
});
|
||||
|
||||
it('updates a board', () => {
|
||||
service.updateBoard(<any>{ id: 1 }).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/boards/1', 'POST');
|
||||
});
|
||||
|
||||
it('handles errors on board update', () => {
|
||||
service.updateBoard(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/boards/1', 'POST', true);
|
||||
});
|
||||
|
||||
it('updates a column', () => {
|
||||
service.updateColumn(<any>{ id: 1 }).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/columns/1', 'POST');
|
||||
});
|
||||
|
||||
it('handles errors on column update', () => {
|
||||
service.updateColumn(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/columns/1', 'POST', true);
|
||||
});
|
||||
|
||||
it('adds a task', () => {
|
||||
service.addTask(<any>{}).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/tasks', 'POST');
|
||||
});
|
||||
|
||||
it('handles errors on task add', () => {
|
||||
service.addTask(<any>{}).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/tasks', 'POST', true);
|
||||
});
|
||||
|
||||
it('updates a task', () => {
|
||||
service.updateTask(<any>{ id: 1 }).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/tasks/1', 'POST');
|
||||
});
|
||||
|
||||
it('handles errors on task update', () => {
|
||||
service.updateTask(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/tasks/1', 'POST', true);
|
||||
});
|
||||
|
||||
it('removes a task', () => {
|
||||
service.removeTask(1).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/tasks/1', 'DELETE');
|
||||
});
|
||||
|
||||
it('handles errors on task removal', () => {
|
||||
service.removeTask(1).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/tasks/1', 'DELETE', true);
|
||||
});
|
||||
|
||||
it('gets task activity', () => {
|
||||
service.getTaskActivity(1).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/activity/task/1', 'GET');
|
||||
});
|
||||
|
||||
it('handles errors on get task activity', () => {
|
||||
service.getTaskActivity(1).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/activity/task/1', 'GET', true);
|
||||
});
|
||||
|
||||
it('updates a comment', () => {
|
||||
service.updateComment(<any>{ id: 1 }).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/comments/1', 'POST');
|
||||
});
|
||||
|
||||
it('handles errors on comment update', () => {
|
||||
service.updateComment(<any>{ id: 1 }).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/comments/1', 'POST', true);
|
||||
});
|
||||
|
||||
it('removes a comment', () => {
|
||||
service.removeComment(1).subscribe(response => {
|
||||
expect(response.data.length).toEqual(0);
|
||||
});
|
||||
|
||||
testCall('api/comments/1', 'DELETE');
|
||||
});
|
||||
|
||||
it('handles errors on comment removal', () => {
|
||||
service.removeComment(1).subscribe(() => {}, response => {
|
||||
expect(response.alerts.length).toEqual(1);
|
||||
});
|
||||
|
||||
testCall('api/comments/1', 'DELETE', true);
|
||||
});
|
||||
|
||||
it('refreshes the API token', () => {
|
||||
service.refreshToken();
|
||||
testCall('api/refresh', 'POST');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
@ -44,6 +44,8 @@ describe('ContextMenu', () => {
|
||||
it('captures parent oncontextmenu events', () => {
|
||||
const parentElement = component.el.nativeElement.parentElement;
|
||||
|
||||
component.el.nativeElement.appendChild(document.createElement('div'));
|
||||
|
||||
expect(parentElement.oncontextmenu).toEqual(jasmine.any(Function));
|
||||
|
||||
parentElement.oncontextmenu({
|
||||
|
@ -10,7 +10,7 @@
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"target": "es5",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
|
Reference in New Issue
Block a user