Compare commits

..

89 Commits

Author SHA1 Message Date
20f960ed67 Merge pull request 'Alpha Release 0.3.1' (#127) from dev into main
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is passing
Reviewed-on: #127
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-01-27 16:43:26 +00:00
e6fe8fcd58 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-27 16:32:04 +00:00
870fd47c83 Merge pull request 'new advanced endpoints feature/125-team_runner' (#126) from feature/125-team_runner into dev
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Reviewed-on: #126
2021-01-27 16:31:45 +00:00
644045db44 Merge branch 'dev' into feature/125-team_runner
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-27 16:31:16 +00:00
aedfcfcc83 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-26 19:15:59 +00:00
db0876015b 🚀Bumped version to v0.3.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-26 20:15:35 +01:00
69417e93c0 Added get runners by team test
All checks were successful
continuous-integration/drone/pr Build is passing
ref #125
2021-01-26 20:13:39 +01:00
f71a22f4dd Added get runners by org test
ref #125
2021-01-26 20:12:14 +01:00
570c34bed0 Created the organizations/runners endpoint
ref #125
2021-01-26 20:06:54 +01:00
7be2971a9e Created the runnerTeam/runners endpoint
ref #125
2021-01-26 19:57:35 +01:00
71898d576c 🧾New changelog file version [CI SKIP] [skip ci] 2021-01-24 17:58:01 +00:00
c964591839 Merge pull request 'Alpha Release 0.3.0' (#122) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #122
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-01-24 17:57:36 +00:00
cc4bf4451c 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-24 17:53:11 +00:00
7dbbd3780d Merge branch 'dev' of git.odit.services:lfk/backend into dev
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2021-01-24 18:52:36 +01:00
3697783e19 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-24 17:52:09 +00:00
161feaf364 Merge pull request 'OrganiZation rename feature/117-organization' (#121) from feature/117-organization into dev
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
Reviewed-on: #121
2021-01-24 17:51:50 +00:00
75e2a44c9c 🚀Bumped version to v0.3.0 2021-01-24 18:48:06 +01:00
cd7e9b86b4 Renamedpermisssions from *Organisation* to *Organization*📝
All checks were successful
continuous-integration/drone/pr Build is passing
ref #117
2021-01-24 18:43:29 +01:00
c6c643ecf1 Renamed files and classed from *Organisation* to *Organization*📝
ref #117
2021-01-24 18:40:46 +01:00
ef15d0d576 Changed organisation* to organization* in descriptions, comments and endoints ✏
ref #117
2021-01-24 18:34:15 +01:00
5660aecb50 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-22 14:13:45 +00:00
6a66dd803b Merge pull request 'Self service registration feature/112-selfservice_registration' (#120) from feature/112-selfservice_registration into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #120
2021-01-22 14:13:25 +00:00
b42f0722d7 Merge branch 'dev' into feature/112-selfservice_registration
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-21 20:02:23 +01:00
45c8bb83be Fixed tests testing for a old responseclass
ref #112
2021-01-21 20:01:44 +01:00
6469e3bc97 Fixed wrong error getting thrown
ref #112
2021-01-21 19:51:40 +01:00
10f98e9c99 Bugfix: turned old entity in response to responseclass
ref #112
2021-01-21 19:49:11 +01:00
e5b6f650b2 Added registration invalid company tests
ref #112
2021-01-21 19:48:45 +01:00
3b2ed3f0f2 Resolved missing relation
ref #112
2021-01-21 19:46:46 +01:00
20e102ec5c Added registration valid company tests
ref #112
2021-01-21 19:46:32 +01:00
5a003945ac Updated response schema error to a more fitting one
ref #112
2021-01-21 19:34:27 +01:00
29aeb046de Added registration invalid company tests
ref #112
2021-01-21 19:34:11 +01:00
72941da1cb Added registration valid citizentests
ref #112
2021-01-21 19:33:55 +01:00
81d2197a3e Added registration invalid citizen tests
ref #112
2021-01-21 19:22:26 +01:00
9dd9304a71 Citizen registration now returns tokens
ref #112
2021-01-21 19:17:40 +01:00
0c87906cc3 Added selfservice get positive test
ref #112
2021-01-21 19:17:25 +01:00
1227408407 Fixed fluctuating test bahaviour
ref #112
2021-01-21 19:10:59 +01:00
f8d7544517 Marked param as optional (default: false)
ref #112
2021-01-21 19:08:43 +01:00
a9843ed459 Updates old tests to the new ss-ktokens
ref #112
2021-01-21 19:08:21 +01:00
46f9503543 Fixed typo
ref #112
2021-01-21 18:45:15 +01:00
c5d0646c42 🧾New changelog file version [CI SKIP] [skip ci] 2021-01-21 17:32:17 +00:00
b441658570 Merge pull request 'Alpha Release 0.2.1' (#119) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #119
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-01-21 17:31:49 +00:00
e95c457e44 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-21 17:15:47 +00:00
6de9d547b7 🚀Bumped version to v0.2.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-21 18:15:24 +01:00
3a93c9c078 🧾New changelog file version [CI SKIP] [skip ci] 2021-01-21 17:14:56 +00:00
36d01a0a89 Merge pull request 'Runner scans endpoint feature/113-runner_scans' (#116) from feature/113-runner_scans into dev
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #116
2021-01-21 17:14:41 +00:00
6434b4dfce Added check for empty token for runner self-service get
ref #112
2021-01-21 18:12:53 +01:00
e964a8ed44 Added self-service get invalid tests
ref #112
2021-01-21 18:12:29 +01:00
c39a59e54e Implemented runner selfservice token generation
ref #112
2021-01-21 18:03:48 +01:00
34c852b12a Specified uft-8 format for string
ref #112
2021-01-21 17:54:11 +01:00
7b00b19fce MAde uuid column unique
ref #112
2021-01-21 17:52:03 +01:00
ad446500f9 Implemented registration key generation
ref #112
2021-01-21 17:48:13 +01:00
d490247d1e Implemented a registration key for organisations
ref #112
2021-01-21 17:30:43 +01:00
dee36395a6 Citizen runners now have to provide an email address for verification
ref #112
2021-01-21 17:19:04 +01:00
6df195b6ec Created a citizenrunner selfservice create action
ref #112
2021-01-21 17:18:25 +01:00
946efef252 Updated Method of removeing the team of citizen runners
ref #112
2021-01-21 17:01:56 +01:00
73b1114883 Added openapi description
ref #112
2021-01-21 16:48:53 +01:00
1b5465bea8 Implemented the citizen runner self-registration endpoint
ref #112
2021-01-21 16:47:13 +01:00
5288c701c1 Implemented the basics for the runner selfservice registration endpoint
ref #112
2021-01-21 16:43:04 +01:00
10af1ba341 Implemented a runner selfservice registration creation action
ref #112
2021-01-21 16:40:47 +01:00
26dff4f418 Added get tests for the /runner/scans endpoint
All checks were successful
continuous-integration/drone/pr Build is passing
ref #113
2021-01-21 16:07:11 +01:00
b5f3dec93b Added a "onlyValid" query param
ref #113
2021-01-21 15:57:56 +01:00
a82fc0fb9e Added a /runners/id/scans endpoint
ref #113
2021-01-21 15:55:29 +01:00
e2ec0a3b64 Readme reorganisation [skip ci] 2021-01-21 15:43:11 +01:00
f4668b6e81 Added sqlite as to env.sample db of choice [skip ci] 2021-01-21 15:27:11 +01:00
d5281348b6 🧾New changelog file version [CI SKIP] [skip ci] 2021-01-20 19:14:43 +00:00
1717df113e Merge pull request 'Runner selfservice info endpoint feature/111-runner_selfservic_info' (#115) from feature/111-runner_selfservic_info into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #115
2021-01-20 19:14:19 +00:00
0355bdbbab Merge branch 'dev' into feature/111-runner_selfservic_info
All checks were successful
continuous-integration/drone/pr Build is passing
2021-01-20 19:13:18 +00:00
02677de5c0 🧾New changelog file version [CI SKIP] [skip ci] 2021-01-20 19:13:07 +00:00
886c1092d6 Merge pull request 'Implemented more seeding feature/110-seeding' (#114) from feature/110-seeding into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #114
2021-01-20 19:12:49 +00:00
191569792c Updated the openapi description
All checks were successful
continuous-integration/drone/pr Build is passing
ref #111
2021-01-20 20:07:16 +01:00
da1fe34249 Implemented the get part of the runner selfservice (no jwts are availdable yet (tm)
ref #111
2021-01-20 20:05:07 +01:00
4ee807973e Fixed wrong amount calculation
ref #111
2021-01-20 20:02:30 +01:00
c5f7cb2c68 Beautified import
ref #111
2021-01-20 19:44:24 +01:00
88a7089289 Created a donation runner response class for the runner selfservice
ref #111
2021-01-20 19:43:53 +01:00
b89f7ac1b4 Created a donation respoinse class for the runner selfservice
ref #111
2021-01-20 19:43:20 +01:00
8079769881 Implemented a method for getting the runner object from a jwt
ref #110
2021-01-20 19:20:08 +01:00
2274b476d6 Added barebones controller for the runner info selfservice
ref #111
2021-01-20 19:05:59 +01:00
e12aedd1aa Fixed the bool converter for null values
All checks were successful
continuous-integration/drone/pr Build is passing
ref #110
2021-01-20 18:28:41 +01:00
434aaf6136 Merge branch 'dev' into feature/110-seeding
Some checks failed
continuous-integration/drone/pr Build is failing
2021-01-20 17:09:14 +00:00
d8b6669d12 📖New license file version [CI SKIP] [skip ci] 2021-01-20 17:07:14 +00:00
7bc603028d The data seeding now only get's triggered on the first time thx to using the key-value
Some checks failed
continuous-integration/drone/pr Build is failing
ref #110
2021-01-20 18:02:08 +01:00
c18012f65a Added bool conversion for testdata seeding env var
ref #110
2021-01-20 17:59:33 +01:00
b15967ff31 Added key-value like db table for config flags
ref #110
2021-01-20 17:58:28 +01:00
2db6510a8a Added a citizen org seeder
ref #110
2021-01-20 17:58:11 +01:00
1837336865 Now creating a test contact
ref #110
2021-01-20 17:38:34 +01:00
eab0e634a2 Now also seeding runners to the test org
ref #110
2021-01-20 17:34:53 +01:00
8870ebdb5e SEED_TEST_DATA is now false by default
ref #110
2021-01-20 17:33:31 +01:00
9df9d9ae80 Added a seeder for runner test data
ref #110
2021-01-20 17:26:04 +01:00
67ba489fe2 Added a config option for test data seeding
ref #110
2021-01-20 17:25:46 +01:00
75 changed files with 1632 additions and 516 deletions

View File

@@ -1,9 +1,10 @@
APP_PORT=4010 APP_PORT=4010
DB_TYPE=bla DB_TYPE=sqlite
DB_HOST=bla DB_HOST=bla
DB_PORT=bla DB_PORT=bla
DB_USER=bla DB_USER=bla
DB_PASSWORD=bla DB_PASSWORD=bla
DB_NAME=bla DB_NAME=./test.sqlite
NODE_ENV=production NODE_ENV=production
POSTALCODE_COUNTRYCODE=DE POSTALCODE_COUNTRYCODE=DE
SEED_TEST_DATA=false

View File

@@ -2,11 +2,106 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v0.3.1](https://git.odit.services/lfk/backend/compare/v0.3.0...v0.3.1)
- Merge pull request 'new advanced endpoints feature/125-team_runner' (#126) from feature/125-team_runner into dev [`870fd47`](https://git.odit.services/lfk/backend/commit/870fd47c83389345d7b24a15df6a4e61e930d140)
- Added get runners by team test [`69417e9`](https://git.odit.services/lfk/backend/commit/69417e93c081422561db1e211b12f32e539010ce)
- 🧾New changelog file version [CI SKIP] [skip ci] [`71898d5`](https://git.odit.services/lfk/backend/commit/71898d576c2620d2f2e2b4336e62f1d04a443201)
- Created the organizations/runners endpoint [`570c34b`](https://git.odit.services/lfk/backend/commit/570c34bed04e359f389a8f427486bf92891f1dcb)
- Created the runnerTeam/runners endpoint [`7be2971`](https://git.odit.services/lfk/backend/commit/7be2971a9e02bf0e784f7fe5cdd82afbbbf7f854)
- 🧾New changelog file version [CI SKIP] [skip ci] [`aedfcfc`](https://git.odit.services/lfk/backend/commit/aedfcfcc8359afd7dba4fa5e515e8e77fbb3fc6e)
- Added get runners by org test [`f71a22f`](https://git.odit.services/lfk/backend/commit/f71a22f4dd9bf14d39ced91908f6f6a5d8395e56)
- 🚀Bumped version to v0.3.1 [`db08760`](https://git.odit.services/lfk/backend/commit/db0876015bf0599dabb21357f172735888c79aa8)
#### [v0.3.0](https://git.odit.services/lfk/backend/compare/v0.2.1...v0.3.0)
> 24 January 2021
- Merge pull request 'Alpha Release 0.3.0' (#122) from dev into main [`c964591`](https://git.odit.services/lfk/backend/commit/c9645918398e62a80341d038b6b6b5c60ee4b1c7)
- Renamed files and classed from *Organisation* to *Organization*📝 [`c6c643e`](https://git.odit.services/lfk/backend/commit/c6c643ecf125f5fdf58b105f97efad32e8545dd4)
- Changed organisation* to organization* in descriptions, comments and endoints ✏ [`ef15d0d`](https://git.odit.services/lfk/backend/commit/ef15d0d57619d79e014e0c0331965ca2bc664254)
- Added registration invalid citizen tests [`81d2197`](https://git.odit.services/lfk/backend/commit/81d2197a3e978ca43bc79720c32d75f8490f08df)
- Implemented registration key generation [`ad44650`](https://git.odit.services/lfk/backend/commit/ad446500f90f945aadc3510377bcfd2123440da0)
- Implemented a runner selfservice registration creation action [`10af1ba`](https://git.odit.services/lfk/backend/commit/10af1ba34148c992e94fa580e1c0210bfaea5112)
- Created a citizenrunner selfservice create action [`6df195b`](https://git.odit.services/lfk/backend/commit/6df195b6ec5fde27f84cbe54992558715b843b87)
- 🧾New changelog file version [CI SKIP] [skip ci] [`5660aec`](https://git.odit.services/lfk/backend/commit/5660aecb50c0e6dd538850c6375d2f692fb7a1f2)
- Implemented a registration key for organisations [`d490247`](https://git.odit.services/lfk/backend/commit/d490247d1e337a680b385d2115e82f79ba54a601)
- Updates old tests to the new ss-ktokens [`a9843ed`](https://git.odit.services/lfk/backend/commit/a9843ed4598485e6e3d18e78b876b6e000ea6e38)
- Added self-service get invalid tests [`e964a8e`](https://git.odit.services/lfk/backend/commit/e964a8ed44109899516c4d3b0dc35fe4990107a1)
- Implemented runner selfservice token generation [`c39a59e`](https://git.odit.services/lfk/backend/commit/c39a59e54ef0b1cc891684283422805af38969e3)
- 🧾New changelog file version [CI SKIP] [skip ci] [`cc4bf44`](https://git.odit.services/lfk/backend/commit/cc4bf4451cf4eac0e0f1bab02119c2dd5e300f48)
- Renamedpermisssions from *Organisation* to *Organization*📝 [`cd7e9b8`](https://git.odit.services/lfk/backend/commit/cd7e9b86b4b9d3e1ef0312f6fff436fcef4a5c94)
- 🧾New changelog file version [CI SKIP] [skip ci] [`3697783`](https://git.odit.services/lfk/backend/commit/3697783e190e36f1168132d75da1eca7be27b4f6)
- Merge pull request 'OrganiZation rename feature/117-organization' (#121) from feature/117-organization into dev [`161feaf`](https://git.odit.services/lfk/backend/commit/161feaf364195c7b85041e06cdefef72d75b8951)
- Added registration valid company tests [`20e102e`](https://git.odit.services/lfk/backend/commit/20e102ec5c52c6a01144d064c96b8b2bd1ccfd00)
- Added registration invalid company tests [`29aeb04`](https://git.odit.services/lfk/backend/commit/29aeb046de769e37fd7257507e36337237697ea0)
- Added registration valid citizentests [`72941da`](https://git.odit.services/lfk/backend/commit/72941da1cb1c31fd6bfcba2ee3704f34bdd73ef0)
- Citizen runners now have to provide an email address for verification [`dee3639`](https://git.odit.services/lfk/backend/commit/dee36395a69da6c5e1bc4e94bd705b0418a6a3ff)
- Implemented the basics for the runner selfservice registration endpoint [`5288c70`](https://git.odit.services/lfk/backend/commit/5288c701c1ac880f3c8b7ece01457aae4bac87d7)
- Added selfservice get positive test [`0c87906`](https://git.odit.services/lfk/backend/commit/0c87906cc3fa5feaf1d7c186f68d978d4ed7fa8e)
- Fixed tests testing for a old responseclass [`45c8bb8`](https://git.odit.services/lfk/backend/commit/45c8bb83be0814bed8856a617de435f4694db76c)
- Fixed typo [`46f9503`](https://git.odit.services/lfk/backend/commit/46f9503543ee011d0780caeefa95748e4be45f58)
- 🧾New changelog file version [CI SKIP] [skip ci] [`c5d0646`](https://git.odit.services/lfk/backend/commit/c5d0646c425f83689bffd862edd568ca0c1b5ad8)
- Added registration invalid company tests [`e5b6f65`](https://git.odit.services/lfk/backend/commit/e5b6f650b25af776a543f7f9c7ccf0000bf07a66)
- Marked param as optional (default: false) [`f8d7544`](https://git.odit.services/lfk/backend/commit/f8d754451769e8361ec2367df7bc586f8fffe8eb)
- Bugfix: turned old entity in response to responseclass [`10f98e9`](https://git.odit.services/lfk/backend/commit/10f98e9c992b1fb45334e65082d7c47af214b6ac)
- Resolved missing relation [`3b2ed3f`](https://git.odit.services/lfk/backend/commit/3b2ed3f0f2557dccddf6ba656b201c196cc24bf0)
- Fixed fluctuating test bahaviour [`1227408`](https://git.odit.services/lfk/backend/commit/1227408407ac66b9689446c1f318b453a9d45069)
- 🚀Bumped version to v0.3.0 [`75e2a44`](https://git.odit.services/lfk/backend/commit/75e2a44c9c7f720d1a5a20611b305e5d56a9155b)
- Merge pull request 'Self service registration feature/112-selfservice_registration' (#120) from feature/112-selfservice_registration into dev [`6a66dd8`](https://git.odit.services/lfk/backend/commit/6a66dd803becb59172e8645c6b55898fb4b4c0b5)
- Implemented the citizen runner self-registration endpoint [`1b5465b`](https://git.odit.services/lfk/backend/commit/1b5465bea810f59cbf8bb1a3e82c062176f79c49)
- Citizen registration now returns tokens [`9dd9304`](https://git.odit.services/lfk/backend/commit/9dd9304a71eae94978710cf9db82dc030ca7a37d)
- Fixed wrong error getting thrown [`6469e3b`](https://git.odit.services/lfk/backend/commit/6469e3bc976c589b42fbac4a95bbee84f67244ee)
- Updated response schema error to a more fitting one [`5a00394`](https://git.odit.services/lfk/backend/commit/5a003945ac7d1a8d446c1bcc8007523b675ab6f5)
- Added check for empty token for runner self-service get [`6434b4d`](https://git.odit.services/lfk/backend/commit/6434b4dfce2da307d66ec5670d570d66ea8af8f8)
- Specified uft-8 format for string [`34c852b`](https://git.odit.services/lfk/backend/commit/34c852b12aaa88e64efa1e0575361c09652e22e1)
- MAde uuid column unique [`7b00b19`](https://git.odit.services/lfk/backend/commit/7b00b19fce3189069bcdbe0d2bcf91322506eb2b)
- Updated Method of removeing the team of citizen runners [`946efef`](https://git.odit.services/lfk/backend/commit/946efef2523c5ceb627b5c465343422cd985832d)
- Added openapi description [`73b1114`](https://git.odit.services/lfk/backend/commit/73b1114883ed2b87ef523130de4c5ca90a11c856)
#### [v0.2.1](https://git.odit.services/lfk/backend/compare/v0.2.0...v0.2.1)
> 21 January 2021
- Merge pull request 'Alpha Release 0.2.1' (#119) from dev into main [`b441658`](https://git.odit.services/lfk/backend/commit/b44165857016c3ecdf0dffe8d324d572524d10ed)
- Created a donation runner response class for the runner selfservice [`88a7089`](https://git.odit.services/lfk/backend/commit/88a7089289e35be4468cb952b311fcb15c54c5a1)
- Readme reorganisation [skip ci] [`e2ec0a3`](https://git.odit.services/lfk/backend/commit/e2ec0a3b64a7388ae85d557dfb66354d70cd1b72)
- Added a seeder for runner test data [`9df9d9a`](https://git.odit.services/lfk/backend/commit/9df9d9ae80277d5ccc753639badb48c4afb13088)
- Created a donation respoinse class for the runner selfservice [`b89f7ac`](https://git.odit.services/lfk/backend/commit/b89f7ac1b4ddd6e53e6e2e8330c1fa2170b48591)
- Added barebones controller for the runner info selfservice [`2274b47`](https://git.odit.services/lfk/backend/commit/2274b476d6caa1de91bb13b6944f8dc233cf446e)
- Implemented a method for getting the runner object from a jwt [`8079769`](https://git.odit.services/lfk/backend/commit/80797698818f456c7746523d5a4f66267fdab10d)
- Added key-value like db table for config flags [`b15967f`](https://git.odit.services/lfk/backend/commit/b15967ff3162e9fe3a634a6f4fc5669f2314cc21)
- Added a /runners/id/scans endpoint [`a82fc0f`](https://git.odit.services/lfk/backend/commit/a82fc0fb9e9c3cbdc6be299b27164c0811e58775)
- Now creating a test contact [`1837336`](https://git.odit.services/lfk/backend/commit/1837336865893ca39d3bc628ff3c57e018a8555d)
- 🧾New changelog file version [CI SKIP] [skip ci] [`02677de`](https://git.odit.services/lfk/backend/commit/02677de5c07b2ac5dcff5567655130ba1b1d48cf)
- The data seeding now only get's triggered on the first time thx to using the key-value [`7bc6030`](https://git.odit.services/lfk/backend/commit/7bc603028dc60d26ffc5327868afbce512966d4d)
- 🧾New changelog file version [CI SKIP] [skip ci] [`3a93c9c`](https://git.odit.services/lfk/backend/commit/3a93c9c078af38ba837b55bf4590867dfd401955)
- Added a "onlyValid" query param [`b5f3dec`](https://git.odit.services/lfk/backend/commit/b5f3dec93bfe4180abbe9ce74094cb1269d0e686)
- Added a citizen org seeder [`2db6510`](https://git.odit.services/lfk/backend/commit/2db6510a8ad83300b286a3bd35ca4db103da72d1)
- 🧾New changelog file version [CI SKIP] [skip ci] [`d528134`](https://git.odit.services/lfk/backend/commit/d5281348b6f3bd6f2e6936ee4497860699b8c3c6)
- 📖New license file version [CI SKIP] [skip ci] [`d8b6669`](https://git.odit.services/lfk/backend/commit/d8b6669d126e64d9e434b5f841ae17a02117822b)
- 🧾New changelog file version [CI SKIP] [skip ci] [`e95c457`](https://git.odit.services/lfk/backend/commit/e95c457e444e9d2e99c2af8b6ee369c36d4ca8ea)
- Beautified import [`c5f7cb2`](https://git.odit.services/lfk/backend/commit/c5f7cb2c68dbee0ab1e0361754f4d4b876666c82)
- 🚀Bumped version to v0.2.1 [`6de9d54`](https://git.odit.services/lfk/backend/commit/6de9d547b736c4538dac5254353d483576337290)
- Merge pull request 'Runner scans endpoint feature/113-runner_scans' (#116) from feature/113-runner_scans into dev [`36d01a0`](https://git.odit.services/lfk/backend/commit/36d01a0a890eb74428679ec6c4fcb14708aaa9fe)
- Added get tests for the /runner/scans endpoint [`26dff4f`](https://git.odit.services/lfk/backend/commit/26dff4f41829e8571231aff3c5d0e3a7c53559d8)
- Implemented the get part of the runner selfservice (no jwts are availdable yet (tm) [`da1fe34`](https://git.odit.services/lfk/backend/commit/da1fe34249a741115c1aeedcade16c5c852e896b)
- Fixed the bool converter for null values [`e12aedd`](https://git.odit.services/lfk/backend/commit/e12aedd1aad6de1f934e9593dda4607a303b2eb5)
- Added a config option for test data seeding [`67ba489`](https://git.odit.services/lfk/backend/commit/67ba489fe2f2a2706d640a668cd0e675ded6a7df)
- SEED_TEST_DATA is now false by default [`8870ebd`](https://git.odit.services/lfk/backend/commit/8870ebdb5e6d9045222440abc2c047929a74b520)
- Added sqlite as to env.sample db of choice [skip ci] [`f4668b6`](https://git.odit.services/lfk/backend/commit/f4668b6e81d7aeac62e24291ffcb39b00ea44aac)
- Merge pull request 'Runner selfservice info endpoint feature/111-runner_selfservic_info' (#115) from feature/111-runner_selfservic_info into dev [`1717df1`](https://git.odit.services/lfk/backend/commit/1717df113edeab2d2628041ee1eccc27380fd379)
- Merge pull request 'Implemented more seeding feature/110-seeding' (#114) from feature/110-seeding into dev [`886c109`](https://git.odit.services/lfk/backend/commit/886c1092d60f8e39357e3b841ed01bb082ede2c4)
- Updated the openapi description [`1915697`](https://git.odit.services/lfk/backend/commit/191569792c9a5cee93718555bba4e7679e4391af)
- Fixed wrong amount calculation [`4ee8079`](https://git.odit.services/lfk/backend/commit/4ee807973e1995681ec549f7c482bc5514a6ec55)
- Added bool conversion for testdata seeding env var [`c18012f`](https://git.odit.services/lfk/backend/commit/c18012f65a704e07acd56870c9ed9f6d06cf97a9)
- Now also seeding runners to the test org [`eab0e63`](https://git.odit.services/lfk/backend/commit/eab0e634a26c1a80e7fa2ccb9dc368f0760b2fd8)
#### [v0.2.0](https://git.odit.services/lfk/backend/compare/v0.1.1...v0.2.0) #### [v0.2.0](https://git.odit.services/lfk/backend/compare/v0.1.1...v0.2.0)
- 🧾New changelog file version [CI SKIP] [skip ci] [`8960aa5`](https://git.odit.services/lfk/backend/commit/8960aa5545ddeb57d4ef42c21c0ca6001dfeaea9) > 20 January 2021
- 🚀Bumped version to v0.2.0 [`ddafd90`](https://git.odit.services/lfk/backend/commit/ddafd90d3e41fb9ee37172a8306c30d8483dfe2c)
- Merge pull request 'Implemented group contacts feature/104-contacts' (#108) from feature/104-contacts into dev [`a0c2b5a`](https://git.odit.services/lfk/backend/commit/a0c2b5ade8d198ec16d33b39e47205e8b03a669f) - Merge pull request 'Alpha Release 0.2.0' (#109) from dev into main [`dd3d93e`](https://git.odit.services/lfk/backend/commit/dd3d93edc7db7ca7f133cb2d8f60c3eaf30bcbf0)
- Updated contact update tests [`c3d008e`](https://git.odit.services/lfk/backend/commit/c3d008ec0ff92f80addbdb93ffc1fa2b3278a8a6) - Updated contact update tests [`c3d008e`](https://git.odit.services/lfk/backend/commit/c3d008ec0ff92f80addbdb93ffc1fa2b3278a8a6)
- Added contact delete tests [`dd7e5da`](https://git.odit.services/lfk/backend/commit/dd7e5dae368a8decd79357f658dda2164fa6f1e7) - Added contact delete tests [`dd7e5da`](https://git.odit.services/lfk/backend/commit/dd7e5dae368a8decd79357f658dda2164fa6f1e7)
- Added contact add valid tests [`e165f01`](https://git.odit.services/lfk/backend/commit/e165f019307e7745357493eacf3e2fa31538122b) - Added contact add valid tests [`e165f01`](https://git.odit.services/lfk/backend/commit/e165f019307e7745357493eacf3e2fa31538122b)
@@ -29,6 +124,7 @@ All notable changes to this project will be documented in this file. Dates are d
- Implemented contact updateing [`28fb983`](https://git.odit.services/lfk/backend/commit/28fb9834e18bde012c5b51cc49a39585d20f7cc1) - Implemented contact updateing [`28fb983`](https://git.odit.services/lfk/backend/commit/28fb9834e18bde012c5b51cc49a39585d20f7cc1)
- Fixed key null constraint [`de82437`](https://git.odit.services/lfk/backend/commit/de824375d3a1da6ee4d78ea39b7da66fc05f2a02) - Fixed key null constraint [`de82437`](https://git.odit.services/lfk/backend/commit/de824375d3a1da6ee4d78ea39b7da66fc05f2a02)
- Implemented contact posting [`11af9c0`](https://git.odit.services/lfk/backend/commit/11af9c02d977dcd6919652256dbdb9fd5438cabd) - Implemented contact posting [`11af9c0`](https://git.odit.services/lfk/backend/commit/11af9c02d977dcd6919652256dbdb9fd5438cabd)
- 🧾New changelog file version [CI SKIP] [skip ci] [`8960aa5`](https://git.odit.services/lfk/backend/commit/8960aa5545ddeb57d4ef42c21c0ca6001dfeaea9)
- Implemented contact group setting on creation [`3b06d1a`](https://git.odit.services/lfk/backend/commit/3b06d1a6ef3c95eb5bb7d485accddabba0a8e4f7) - Implemented contact group setting on creation [`3b06d1a`](https://git.odit.services/lfk/backend/commit/3b06d1a6ef3c95eb5bb7d485accddabba0a8e4f7)
- 🧾New changelog file version [CI SKIP] [skip ci] [`32e054e`](https://git.odit.services/lfk/backend/commit/32e054eb84c869210fd483583ae5a6d0e2249cf9) - 🧾New changelog file version [CI SKIP] [skip ci] [`32e054e`](https://git.odit.services/lfk/backend/commit/32e054eb84c869210fd483583ae5a6d0e2249cf9)
- Switched Address to embedded entity [`7fbe649`](https://git.odit.services/lfk/backend/commit/7fbe649dc90f4bb9f240c5a80fed447048e5e105) - Switched Address to embedded entity [`7fbe649`](https://git.odit.services/lfk/backend/commit/7fbe649dc90f4bb9f240c5a80fed447048e5e105)
@@ -39,11 +135,14 @@ All notable changes to this project will be documented in this file. Dates are d
- Fixed donor address check [`4824547`](https://git.odit.services/lfk/backend/commit/4824547dde4d7f90e9e2377a26df34cabf082fdb) - Fixed donor address check [`4824547`](https://git.odit.services/lfk/backend/commit/4824547dde4d7f90e9e2377a26df34cabf082fdb)
- Updated contact delete tests [`8ae53f1`](https://git.odit.services/lfk/backend/commit/8ae53f1c4930e2fd72eb230a5314336f3a45a611) - Updated contact delete tests [`8ae53f1`](https://git.odit.services/lfk/backend/commit/8ae53f1c4930e2fd72eb230a5314336f3a45a611)
- Added address to contact response [`09e429f`](https://git.odit.services/lfk/backend/commit/09e429fc676c7dd370bba0495b072f81867bd250) - Added address to contact response [`09e429f`](https://git.odit.services/lfk/backend/commit/09e429fc676c7dd370bba0495b072f81867bd250)
- Updated comments [`a4e8311`](https://git.odit.services/lfk/backend/commit/a4e8311cbd22588ecb4dc2fdbe05397b07d336f8)
- Updated the responseclasses to use the new address implementation [`dafac06`](https://git.odit.services/lfk/backend/commit/dafac06bc84d1b237096a561b3adcd3ca5cb1dd8) - Updated the responseclasses to use the new address implementation [`dafac06`](https://git.odit.services/lfk/backend/commit/dafac06bc84d1b237096a561b3adcd3ca5cb1dd8)
- Added address validity check [`ae7c5ff`](https://git.odit.services/lfk/backend/commit/ae7c5ff0c387e9337d01a9dd819a4dddc208f6dd)
- 🧾New changelog file version [CI SKIP] [skip ci] [`da9a359`](https://git.odit.services/lfk/backend/commit/da9a3592510eacd2d67a127dc61e954343e0444b)
- 🚀Bumped version to v0.2.0 [`ddafd90`](https://git.odit.services/lfk/backend/commit/ddafd90d3e41fb9ee37172a8306c30d8483dfe2c)
- Merge pull request 'Implemented group contacts feature/104-contacts' (#108) from feature/104-contacts into dev [`a0c2b5a`](https://git.odit.services/lfk/backend/commit/a0c2b5ade8d198ec16d33b39e47205e8b03a669f)
- Updated comments [`a4e8311`](https://git.odit.services/lfk/backend/commit/a4e8311cbd22588ecb4dc2fdbe05397b07d336f8)
- Removed (now useless) relations [`673dea2`](https://git.odit.services/lfk/backend/commit/673dea2e5754e99ff77f7556d4fc03d4cca28a94) - Removed (now useless) relations [`673dea2`](https://git.odit.services/lfk/backend/commit/673dea2e5754e99ff77f7556d4fc03d4cca28a94)
- Added missing id property [`6b4b16c`](https://git.odit.services/lfk/backend/commit/6b4b16c13b0c2f55745ded3431cad2f4986be296) - Added missing id property [`6b4b16c`](https://git.odit.services/lfk/backend/commit/6b4b16c13b0c2f55745ded3431cad2f4986be296)
- Added address validity check [`ae7c5ff`](https://git.odit.services/lfk/backend/commit/ae7c5ff0c387e9337d01a9dd819a4dddc208f6dd)
- 🧾New changelog file version [CI SKIP] [skip ci] [`f53894b`](https://git.odit.services/lfk/backend/commit/f53894b16ac1c06ecbeeb0b63a56ac438b2fbe1b) - 🧾New changelog file version [CI SKIP] [skip ci] [`f53894b`](https://git.odit.services/lfk/backend/commit/f53894b16ac1c06ecbeeb0b63a56ac438b2fbe1b)
- Updated comments [`8bc01d3`](https://git.odit.services/lfk/backend/commit/8bc01d3f2406ce8e58c2ab2963c858495c510dcf) - Updated comments [`8bc01d3`](https://git.odit.services/lfk/backend/commit/8bc01d3f2406ce8e58c2ab2963c858495c510dcf)
- Fixed contact cascading [`179c2a5`](https://git.odit.services/lfk/backend/commit/179c2a5157fca036acf8d0e6a51821d377860bc1) - Fixed contact cascading [`179c2a5`](https://git.odit.services/lfk/backend/commit/179c2a5157fca036acf8d0e6a51821d377860bc1)

View File

@@ -2,20 +2,18 @@
Backend Server Backend Server
## Quickstart 🐳
> Use this to run the backend with a postgresql db in docker
1. Clone the repo or copy the docker-compose
2. Run in toe folder that contains the docker-compose file: `docker-compose up -d`
3. Visit http://127.0.0.1:4010/api/docs to check if the server is running
4. You can now use the default admin user (`demo:demo`)
## Dev Setup 🛠 ## Dev Setup 🛠
> Local dev setup utilizing sqlite3 as the database.
### Local w/ sqlite 1. Rename the .env.example file to .env (you can adjust app port and other settings, if needed)
1. Create a .env file in the project root containing:
```
APP_PORT=4010
DB_TYPE=sqlite
DB_HOST=bla
DB_PORT=bla
DB_USER=bla
DB_PASSWORD=bla
DB_NAME=./test.sqlite
```
2. Install Dependencies 2. Install Dependencies
```bash ```bash
yarn yarn
@@ -25,15 +23,21 @@ Backend Server
yarn dev yarn dev
``` ```
### Generate Docs ### Run Tests
```
yarn docs
```
### Docker w/ postgres 🐳
```bash ```bash
docker-compose up --build # Run tests once (server has to run)
yarn test
# Run test in watch mode (reruns on change)
yarn test:watch
# Run test in ci mode (automaticly starts the dev server)
yarn test:ci
```
### Generate Docs
```bash
yarn docs
``` ```
## Recommended Editor ## Recommended Editor
@@ -42,22 +46,19 @@ docker-compose up --build
### Recommended Extensions ### Recommended Extensions
- will be automatically recommended via ./vscode/extensions.json * will be automatically recommended via ./vscode/extensions.json
## Branches ## Staging
- main: Protected "release" branch ### Branches & Tags
- dev: Current dev branch for merging the different features - only push for merges or minor changes! * vX.Y.Z: Release tags created from the main branch
- feature/xyz: Feature branches - `feature/issueid-title` * The version numbers follow the semver standard
- bugfix/xyz: Branches for bugfixes - `bugfix/issueid-title` (no id for readme changes needed) * A new release tag automaticly triggers the release ci pipeline
* main: Protected "release" branch
* The latest tag of the docker image get's build from this
## File Structure * New releases get created as tags from this
* dev: Current dev branch for merging the different feature branches and bugfixes
- src/models/entities\* - database models (typeorm entities) * The dev tag of the docker image get's build from this
- src/models/actions\* - actions models * Only push minor changes to this branch!
- src/models/responses\* - response models * To merge a feature branch into this please create a pull request
- src/controllers/\* - routing-controllers * feature/xyz: Feature branches - nameing scheme: `feature/issueid-title`
- src/loaders/\* - loaders for the different init steps of the api server * bugfix/xyz: Branches for bugfixes - nameing scheme:`bugfix/issueid-title`
- src/middlewares/\* - express middlewares (mainly auth r/n)
- src/errors/* - our custom (http) errors
- src/routes/\* - express routes for everything we don't do via routing-controllers (depreciated)

View File

@@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-backend", "name": "@odit/lfk-backend",
"version": "0.2.0", "version": "0.3.1",
"main": "src/app.ts", "main": "src/app.ts",
"repository": "https://git.odit.services/lfk/backend", "repository": "https://git.odit.services/lfk/backend",
"author": { "author": {

View File

@@ -9,7 +9,8 @@ export const config = {
jwt_secret: process.env.JWT_SECRET || "secretjwtsecret", jwt_secret: process.env.JWT_SECRET || "secretjwtsecret",
phone_validation_countrycode: getPhoneCodeLocale(), phone_validation_countrycode: getPhoneCodeLocale(),
postalcode_validation_countrycode: getPostalCodeLocale(), postalcode_validation_countrycode: getPostalCodeLocale(),
version: process.env.VERSION || require('../package.json').version version: process.env.VERSION || require('../package.json').version,
seedTestData: getDataSeeding()
} }
let errors = 0 let errors = 0
if (typeof config.internal_port !== "number") { if (typeof config.internal_port !== "number") {
@@ -30,4 +31,11 @@ function getPostalCodeLocale(): any {
return null; return null;
} }
} }
function getDataSeeding(): Boolean {
try {
return JSON.parse(process.env.SEED_TEST_DATA);
} catch (error) {
return false;
}
}
export let e = errors export let e = errors

View File

@@ -28,7 +28,7 @@ export class GroupContactController {
@OpenAPI({ description: 'Lists all contacts. <br> This includes the contact\'s associated groups.' }) @OpenAPI({ description: 'Lists all contacts. <br> This includes the contact\'s associated groups.' })
async getAll() { async getAll() {
let responseContacts: ResponseGroupContact[] = new Array<ResponseGroupContact>(); let responseContacts: ResponseGroupContact[] = new Array<ResponseGroupContact>();
const contacts = await this.contactRepository.find({ relations: ['groups'] }); const contacts = await this.contactRepository.find({ relations: ['groups', 'groups.parentGroup'] });
contacts.forEach(contact => { contacts.forEach(contact => {
responseContacts.push(contact.toResponse()); responseContacts.push(contact.toResponse());
}); });
@@ -42,7 +42,7 @@ export class GroupContactController {
@OnUndefined(GroupContactNotFoundError) @OnUndefined(GroupContactNotFoundError)
@OpenAPI({ description: 'Lists all information about the contact whose id got provided. <br> This includes the contact\'s associated groups.' }) @OpenAPI({ description: 'Lists all information about the contact whose id got provided. <br> This includes the contact\'s associated groups.' })
async getOne(@Param('id') id: number) { async getOne(@Param('id') id: number) {
let contact = await this.contactRepository.findOne({ id: id }, { relations: ['groups'] }) let contact = await this.contactRepository.findOne({ id: id }, { relations: ['groups', 'groups.parentGroup'] })
if (!contact) { throw new GroupContactNotFoundError(); } if (!contact) { throw new GroupContactNotFoundError(); }
return contact.toResponse(); return contact.toResponse();
} }
@@ -61,7 +61,7 @@ export class GroupContactController {
} }
contact = await this.contactRepository.save(contact) contact = await this.contactRepository.save(contact)
return (await this.contactRepository.findOne({ id: contact.id }, { relations: ['groups'] })).toResponse(); return (await this.contactRepository.findOne({ id: contact.id }, { relations: ['groups', 'groups.parentGroup'] })).toResponse();
} }
@Put('/:id') @Put('/:id')
@@ -83,7 +83,7 @@ export class GroupContactController {
} }
await this.contactRepository.save(await contact.update(oldContact)); await this.contactRepository.save(await contact.update(oldContact));
return (await this.contactRepository.findOne({ id: contact.id }, { relations: ['groups'] })).toResponse(); return (await this.contactRepository.findOne({ id: contact.id }, { relations: ['groups', 'groups.parentGroup'] })).toResponse();
} }
@Delete('/:id') @Delete('/:id')
@@ -95,7 +95,7 @@ export class GroupContactController {
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let contact = await this.contactRepository.findOne({ id: id }); let contact = await this.contactRepository.findOne({ id: id });
if (!contact) { return null; } if (!contact) { return null; }
const responseContact = await this.contactRepository.findOne(contact, { relations: ['groups'] }); const responseContact = await this.contactRepository.findOne(contact, { relations: ['groups', 'groups.parentGroup'] });
for (let group of responseContact.groups) { for (let group of responseContact.groups) {
group.contact = null; group.contact = null;
await getConnection().getRepository(RunnerGroup).save(group); await getConnection().getRepository(RunnerGroup).save(group);

View File

@@ -36,7 +36,7 @@ export class ImportController {
return responseRunners; return responseRunners;
} }
@Post('/organisations/:id/import') @Post('/organizations/:id/import')
@ContentType("application/json") @ContentType("application/json")
@ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 }) @ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 })
@ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 })
@@ -78,7 +78,7 @@ export class ImportController {
return await this.postJSON(importRunners, groupID); return await this.postJSON(importRunners, groupID);
} }
@Post('/organisations/:id/import/csv') @Post('/organizations/:id/import/csv')
@ContentType("application/json") @ContentType("application/json")
@UseBefore(RawBodyMiddleware) @UseBefore(RawBodyMiddleware)
@ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 }) @ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 })

View File

@@ -8,6 +8,8 @@ import { UpdateRunner } from '../models/actions/update/UpdateRunner';
import { Runner } from '../models/entities/Runner'; import { Runner } from '../models/entities/Runner';
import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseEmpty } from '../models/responses/ResponseEmpty';
import { ResponseRunner } from '../models/responses/ResponseRunner'; import { ResponseRunner } from '../models/responses/ResponseRunner';
import { ResponseScan } from '../models/responses/ResponseScan';
import { ResponseTrackScan } from '../models/responses/ResponseTrackScan';
import { DonationController } from './DonationController'; import { DonationController } from './DonationController';
import { RunnerCardController } from './RunnerCardController'; import { RunnerCardController } from './RunnerCardController';
import { ScanController } from './ScanController'; import { ScanController } from './ScanController';
@@ -49,6 +51,31 @@ export class RunnerController {
return new ResponseRunner(runner); return new ResponseRunner(runner);
} }
@Get('/:id/scans')
@Authorized(["RUNNER:GET", "SCAN:GET"])
@ResponseSchema(ResponseScan, { isArray: true })
@ResponseSchema(ResponseTrackScan, { isArray: true })
@ResponseSchema(RunnerNotFoundError, { statusCode: 404 })
@OpenAPI({ description: 'Lists all scans of the runner whose id got provided. <br> If you only want the valid scans just add the ?onlyValid=true query param.' })
async getScans(@Param('id') id: number, onlyValid?: boolean) {
let responseScans: ResponseScan[] = new Array<ResponseScan>();
let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'scans.track', 'scans.station', 'scans.runner'] })
if (!runner) { throw new RunnerNotFoundError(); }
if (!onlyValid) {
for (let scan of runner.scans) {
responseScans.push(scan.toResponse());
}
}
else {
for (let scan of runner.validScans) {
responseScans.push(scan.toResponse());
}
}
return responseScans;
}
@Post() @Post()
@Authorized("RUNNER:CREATE") @Authorized("RUNNER:CREATE")
@ResponseSchema(ResponseRunner) @ResponseSchema(ResponseRunner)

View File

@@ -1,127 +0,0 @@
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { getConnectionManager, Repository } from 'typeorm';
import { RunnerOrganisationHasRunnersError, RunnerOrganisationHasTeamsError, RunnerOrganisationIdsNotMatchingError, RunnerOrganisationNotFoundError } from '../errors/RunnerOrganisationErrors';
import { CreateRunnerOrganisation } from '../models/actions/create/CreateRunnerOrganisation';
import { UpdateRunnerOrganisation } from '../models/actions/update/UpdateRunnerOrganisation';
import { RunnerOrganisation } from '../models/entities/RunnerOrganisation';
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
import { ResponseRunnerOrganisation } from '../models/responses/ResponseRunnerOrganisation';
import { RunnerController } from './RunnerController';
import { RunnerTeamController } from './RunnerTeamController';
@JsonController('/organisations')
@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
export class RunnerOrganisationController {
private runnerOrganisationRepository: Repository<RunnerOrganisation>;
/**
* Gets the repository of this controller's model/entity.
*/
constructor() {
this.runnerOrganisationRepository = getConnectionManager().get().getRepository(RunnerOrganisation);
}
@Get()
@Authorized("ORGANISATION:GET")
@ResponseSchema(ResponseRunnerOrganisation, { isArray: true })
@OpenAPI({ description: 'Lists all organisations. <br> This includes their address, contact and teams (if existing/associated).' })
async getAll() {
let responseTeams: ResponseRunnerOrganisation[] = new Array<ResponseRunnerOrganisation>();
const runners = await this.runnerOrganisationRepository.find({ relations: ['contact', 'teams'] });
runners.forEach(runner => {
responseTeams.push(new ResponseRunnerOrganisation(runner));
});
return responseTeams;
}
@Get('/:id')
@Authorized("ORGANISATION:GET")
@ResponseSchema(ResponseRunnerOrganisation)
@ResponseSchema(RunnerOrganisationNotFoundError, { statusCode: 404 })
@OnUndefined(RunnerOrganisationNotFoundError)
@OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' })
async getOne(@Param('id') id: number) {
let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['contact', 'teams'] });
if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); }
return new ResponseRunnerOrganisation(runnerOrg);
}
@Post()
@Authorized("ORGANISATION:CREATE")
@ResponseSchema(ResponseRunnerOrganisation)
@OpenAPI({ description: 'Create a new organsisation.' })
async post(@Body({ validate: true }) createRunnerOrganisation: CreateRunnerOrganisation) {
let runnerOrganisation;
try {
runnerOrganisation = await createRunnerOrganisation.toEntity();
} catch (error) {
throw error;
}
runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation);
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['contact', 'teams'] }));
}
@Put('/:id')
@Authorized("ORGANISATION:UPDATE")
@ResponseSchema(ResponseRunnerOrganisation)
@ResponseSchema(RunnerOrganisationNotFoundError, { statusCode: 404 })
@ResponseSchema(RunnerOrganisationIdsNotMatchingError, { statusCode: 406 })
@OpenAPI({ description: "Update the organisation whose id you provided. <br> Please remember that ids can't be changed." })
async put(@Param('id') id: number, @Body({ validate: true }) updateOrganisation: UpdateRunnerOrganisation) {
let oldRunnerOrganisation = await this.runnerOrganisationRepository.findOne({ id: id });
if (!oldRunnerOrganisation) {
throw new RunnerOrganisationNotFoundError();
}
if (oldRunnerOrganisation.id != updateOrganisation.id) {
throw new RunnerOrganisationIdsNotMatchingError();
}
await this.runnerOrganisationRepository.save(await updateOrganisation.update(oldRunnerOrganisation));
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['contact', 'teams'] }));
}
@Delete('/:id')
@Authorized("ORGANISATION:DELETE")
@ResponseSchema(ResponseRunnerOrganisation)
@ResponseSchema(ResponseEmpty, { statusCode: 204 })
@ResponseSchema(RunnerOrganisationHasTeamsError, { statusCode: 406 })
@ResponseSchema(RunnerOrganisationHasRunnersError, { statusCode: 406 })
@OnUndefined(204)
@OpenAPI({ description: 'Delete the organsisation whose id you provided. <br> If the organisation still has runners and/or teams associated this will fail. <br> To delete the organisation with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while). <br> This won\'t delete the associated contact. <br> If no organisation with this id exists it will just return 204(no content).' })
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let organisation = await this.runnerOrganisationRepository.findOne({ id: id });
if (!organisation) { return null; }
let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['contact', 'runners', 'teams'] });
if (!force) {
if (runnerOrganisation.teams.length != 0) {
throw new RunnerOrganisationHasTeamsError();
}
}
const teamController = new RunnerTeamController()
for (let team of runnerOrganisation.teams) {
await teamController.remove(team.id, true);
}
if (!force) {
if (runnerOrganisation.runners.length != 0) {
throw new RunnerOrganisationHasRunnersError();
}
}
const runnerController = new RunnerController()
for (let runner of runnerOrganisation.runners) {
await runnerController.remove(runner.id, true);
}
const responseOrganisation = new ResponseRunnerOrganisation(runnerOrganisation);
await this.runnerOrganisationRepository.delete(organisation);
return responseOrganisation;
}
}

View File

@@ -0,0 +1,145 @@
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { getConnectionManager, Repository } from 'typeorm';
import { RunnerOrganizationHasRunnersError, RunnerOrganizationHasTeamsError, RunnerOrganizationIdsNotMatchingError, RunnerOrganizationNotFoundError } from '../errors/RunnerOrganizationErrors';
import { CreateRunnerOrganization } from '../models/actions/create/CreateRunnerOrganization';
import { UpdateRunnerOrganization } from '../models/actions/update/UpdateRunnerOrganization';
import { Runner } from '../models/entities/Runner';
import { RunnerOrganization } from '../models/entities/RunnerOrganization';
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
import { ResponseRunner } from '../models/responses/ResponseRunner';
import { ResponseRunnerOrganization } from '../models/responses/ResponseRunnerOrganization';
import { RunnerController } from './RunnerController';
import { RunnerTeamController } from './RunnerTeamController';
@JsonController('/organizations')
@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
export class RunnerOrganizationController {
private runnerOrganizationRepository: Repository<RunnerOrganization>;
/**
* Gets the repository of this controller's model/entity.
*/
constructor() {
this.runnerOrganizationRepository = getConnectionManager().get().getRepository(RunnerOrganization);
}
@Get()
@Authorized("ORGANIZATION:GET")
@ResponseSchema(ResponseRunnerOrganization, { isArray: true })
@OpenAPI({ description: 'Lists all organizations. <br> This includes their address, contact and teams (if existing/associated).' })
async getAll() {
let responseTeams: ResponseRunnerOrganization[] = new Array<ResponseRunnerOrganization>();
const runners = await this.runnerOrganizationRepository.find({ relations: ['contact', 'teams'] });
runners.forEach(runner => {
responseTeams.push(new ResponseRunnerOrganization(runner));
});
return responseTeams;
}
@Get('/:id')
@Authorized("ORGANIZATION:GET")
@ResponseSchema(ResponseRunnerOrganization)
@ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 })
@OnUndefined(RunnerOrganizationNotFoundError)
@OpenAPI({ description: 'Lists all information about the organization whose id got provided.' })
async getOne(@Param('id') id: number) {
let runnerOrg = await this.runnerOrganizationRepository.findOne({ id: id }, { relations: ['contact', 'teams'] });
if (!runnerOrg) { throw new RunnerOrganizationNotFoundError(); }
return new ResponseRunnerOrganization(runnerOrg);
}
@Get('/:id/runners')
@Authorized(["RUNNER:GET", "SCAN:GET"])
@ResponseSchema(ResponseRunner, { isArray: true })
@ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 })
@OpenAPI({ description: 'Lists all runners from this org and it\'s teams (if you don\'t provide the ?onlyDirect=true param). <br> This includes the runner\'s group and distance ran.' })
async getRunners(@Param('id') id: number, @QueryParam('onlyDirect') onlyDirect: boolean) {
let responseRunners: ResponseRunner[] = new Array<ResponseRunner>();
let runners: Runner[];
if (!onlyDirect) { runners = (await this.runnerOrganizationRepository.findOne({ id: id }, { relations: ['runners', 'runners.group', 'runners.scans', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.group', 'teams.runners.scans', 'teams.runners.scans.track'] })).allRunners; }
else { runners = (await this.runnerOrganizationRepository.findOne({ id: id }, { relations: ['runners', 'runners.group', 'runners.scans', 'runners.scans.track'] })).runners; }
runners.forEach(runner => {
responseRunners.push(new ResponseRunner(runner));
});
return responseRunners;
}
@Post()
@Authorized("ORGANIZATION:CREATE")
@ResponseSchema(ResponseRunnerOrganization)
@OpenAPI({ description: 'Create a new organsisation.' })
async post(@Body({ validate: true }) createRunnerOrganization: CreateRunnerOrganization) {
let runnerOrganization;
try {
runnerOrganization = await createRunnerOrganization.toEntity();
} catch (error) {
throw error;
}
runnerOrganization = await this.runnerOrganizationRepository.save(runnerOrganization);
return new ResponseRunnerOrganization(await this.runnerOrganizationRepository.findOne(runnerOrganization, { relations: ['contact', 'teams'] }));
}
@Put('/:id')
@Authorized("ORGANIZATION:UPDATE")
@ResponseSchema(ResponseRunnerOrganization)
@ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 })
@ResponseSchema(RunnerOrganizationIdsNotMatchingError, { statusCode: 406 })
@OpenAPI({ description: "Update the organization whose id you provided. <br> Please remember that ids can't be changed." })
async put(@Param('id') id: number, @Body({ validate: true }) updateOrganization: UpdateRunnerOrganization) {
let oldRunnerOrganization = await this.runnerOrganizationRepository.findOne({ id: id });
if (!oldRunnerOrganization) {
throw new RunnerOrganizationNotFoundError();
}
if (oldRunnerOrganization.id != updateOrganization.id) {
throw new RunnerOrganizationIdsNotMatchingError();
}
await this.runnerOrganizationRepository.save(await updateOrganization.update(oldRunnerOrganization));
return new ResponseRunnerOrganization(await this.runnerOrganizationRepository.findOne(id, { relations: ['contact', 'teams'] }));
}
@Delete('/:id')
@Authorized("ORGANIZATION:DELETE")
@ResponseSchema(ResponseRunnerOrganization)
@ResponseSchema(ResponseEmpty, { statusCode: 204 })
@ResponseSchema(RunnerOrganizationHasTeamsError, { statusCode: 406 })
@ResponseSchema(RunnerOrganizationHasRunnersError, { statusCode: 406 })
@OnUndefined(204)
@OpenAPI({ description: 'Delete the organsisation whose id you provided. <br> If the organization still has runners and/or teams associated this will fail. <br> To delete the organization with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while). <br> This won\'t delete the associated contact. <br> If no organization with this id exists it will just return 204(no content).' })
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let organization = await this.runnerOrganizationRepository.findOne({ id: id });
if (!organization) { return null; }
let runnerOrganization = await this.runnerOrganizationRepository.findOne(organization, { relations: ['contact', 'runners', 'teams'] });
if (!force) {
if (runnerOrganization.teams.length != 0) {
throw new RunnerOrganizationHasTeamsError();
}
}
const teamController = new RunnerTeamController()
for (let team of runnerOrganization.teams) {
await teamController.remove(team.id, true);
}
if (!force) {
if (runnerOrganization.runners.length != 0) {
throw new RunnerOrganizationHasRunnersError();
}
}
const runnerController = new RunnerController()
for (let runner of runnerOrganization.runners) {
await runnerController.remove(runner.id, true);
}
const responseOrganization = new ResponseRunnerOrganization(runnerOrganization);
await this.runnerOrganizationRepository.delete(organization);
return responseOrganization;
}
}

View File

@@ -0,0 +1,98 @@
import * as jwt from "jsonwebtoken";
import { Body, Get, JsonController, OnUndefined, Param, Post } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { getConnectionManager, Repository } from 'typeorm';
import { config } from '../config';
import { InvalidCredentialsError, JwtNotProvidedError } from '../errors/AuthError';
import { RunnerEmailNeededError, RunnerNotFoundError } from '../errors/RunnerErrors';
import { RunnerOrganizationNotFoundError } from '../errors/RunnerOrganizationErrors';
import { JwtCreator } from '../jwtcreator';
import { CreateSelfServiceCitizenRunner } from '../models/actions/create/CreateSelfServiceCitizenRunner';
import { CreateSelfServiceRunner } from '../models/actions/create/CreateSelfServiceRunner';
import { Runner } from '../models/entities/Runner';
import { RunnerGroup } from '../models/entities/RunnerGroup';
import { RunnerOrganization } from '../models/entities/RunnerOrganization';
import { ResponseSelfServiceRunner } from '../models/responses/ResponseSelfServiceRunner';
@JsonController('/runners')
export class RunnerSelfServiceController {
private runnerRepository: Repository<Runner>;
private orgRepository: Repository<RunnerOrganization>;
/**
* Gets the repository of this controller's model/entity.
*/
constructor() {
this.runnerRepository = getConnectionManager().get().getRepository(Runner);
this.orgRepository = getConnectionManager().get().getRepository(RunnerOrganization);
}
@Get('/me/:jwt')
@ResponseSchema(ResponseSelfServiceRunner)
@ResponseSchema(RunnerNotFoundError, { statusCode: 404 })
@OnUndefined(RunnerNotFoundError)
@OpenAPI({ description: 'Lists all information about yourself. <br> Please provide your runner jwt(that code we gave you during registration) for auth. <br> If you lost your jwt/personalized link please contact support.' })
async get(@Param('jwt') token: string) {
return (new ResponseSelfServiceRunner(await this.getRunner(token)));
}
@Post('/register')
@ResponseSchema(ResponseSelfServiceRunner)
@ResponseSchema(RunnerEmailNeededError, { statusCode: 406 })
@OpenAPI({ description: 'Create a new selfservice runner in the citizen org. <br> This endpoint shoud be used to allow "everyday citizen" to register themselves. <br> You have to provide a mail address, b/c the future we\'ll implement email verification.' })
async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner) {
let runner = await createRunner.toEntity();
runner = await this.runnerRepository.save(runner);
let response = new ResponseSelfServiceRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] }));
response.token = JwtCreator.createSelfService(runner);
return response;
}
@Post('/register/:token')
@ResponseSchema(ResponseSelfServiceRunner)
@ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 })
@OpenAPI({ description: 'Create a new selfservice runner in a provided org. <br> The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.' })
async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner) {
const org = await this.getOrgansisation(token);
let runner = await createRunner.toEntity(org);
runner = await this.runnerRepository.save(runner);
let response = new ResponseSelfServiceRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] }));
response.token = JwtCreator.createSelfService(runner);
return response;
}
/**
* Get's a runner by a provided jwt token.
* @param token The runner jwt provided by the runner to identitfy themselves.
*/
private async getRunner(token: string): Promise<Runner> {
if (token == "") { throw new JwtNotProvidedError(); }
let jwtPayload = undefined
try {
jwtPayload = <any>jwt.verify(token, config.jwt_secret);
} catch (error) {
throw new InvalidCredentialsError();
}
const runner = await this.runnerRepository.findOne({ id: jwtPayload["id"] }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] });
if (!runner) { throw new RunnerNotFoundError() }
return runner;
}
/**
* Get's a runner org by a provided registration api key.
* @param token The organization's registration api token.
*/
private async getOrgansisation(token: string): Promise<RunnerGroup> {
token = Buffer.from(token, 'base64').toString('utf8');
const organization = await this.orgRepository.findOne({ key: token });
if (!organization) { throw new RunnerOrganizationNotFoundError; }
return organization;
}
}

View File

@@ -6,6 +6,7 @@ import { CreateRunnerTeam } from '../models/actions/create/CreateRunnerTeam';
import { UpdateRunnerTeam } from '../models/actions/update/UpdateRunnerTeam'; import { UpdateRunnerTeam } from '../models/actions/update/UpdateRunnerTeam';
import { RunnerTeam } from '../models/entities/RunnerTeam'; import { RunnerTeam } from '../models/entities/RunnerTeam';
import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseEmpty } from '../models/responses/ResponseEmpty';
import { ResponseRunner } from '../models/responses/ResponseRunner';
import { ResponseRunnerTeam } from '../models/responses/ResponseRunnerTeam'; import { ResponseRunnerTeam } from '../models/responses/ResponseRunnerTeam';
import { RunnerController } from './RunnerController'; import { RunnerController } from './RunnerController';
@@ -25,7 +26,7 @@ export class RunnerTeamController {
@Get() @Get()
@Authorized("TEAM:GET") @Authorized("TEAM:GET")
@ResponseSchema(ResponseRunnerTeam, { isArray: true }) @ResponseSchema(ResponseRunnerTeam, { isArray: true })
@OpenAPI({ description: 'Lists all teams. <br> This includes their parent organisation and contact (if existing/associated).' }) @OpenAPI({ description: 'Lists all teams. <br> This includes their parent organization and contact (if existing/associated).' })
async getAll() { async getAll() {
let responseTeams: ResponseRunnerTeam[] = new Array<ResponseRunnerTeam>(); let responseTeams: ResponseRunnerTeam[] = new Array<ResponseRunnerTeam>();
const runners = await this.runnerTeamRepository.find({ relations: ['parentGroup', 'contact'] }); const runners = await this.runnerTeamRepository.find({ relations: ['parentGroup', 'contact'] });
@@ -47,6 +48,20 @@ export class RunnerTeamController {
return new ResponseRunnerTeam(runnerTeam); return new ResponseRunnerTeam(runnerTeam);
} }
@Get('/:id/runners')
@Authorized(["RUNNER:GET", "SCAN:GET"])
@ResponseSchema(ResponseRunner, { isArray: true })
@ResponseSchema(RunnerTeamNotFoundError, { statusCode: 404 })
@OpenAPI({ description: 'Lists all runners from this team. <br> This includes the runner\'s group and distance ran.' })
async getRunners(@Param('id') id: number) {
let responseRunners: ResponseRunner[] = new Array<ResponseRunner>();
const runners = (await this.runnerTeamRepository.findOne({ id: id }, { relations: ['runners', 'runners.group', 'runners.scans', 'runners.scans.track'] })).runners;
runners.forEach(runner => {
responseRunners.push(new ResponseRunner(runner));
});
return responseRunners;
}
@Post() @Post()
@Authorized("TEAM:CREATE") @Authorized("TEAM:CREATE")
@ResponseSchema(ResponseRunnerTeam) @ResponseSchema(ResponseRunnerTeam)

View File

@@ -4,12 +4,12 @@ import { getConnection } from 'typeorm';
import StatsAuth from '../middlewares/StatsAuth'; import StatsAuth from '../middlewares/StatsAuth';
import { Donation } from '../models/entities/Donation'; import { Donation } from '../models/entities/Donation';
import { Runner } from '../models/entities/Runner'; import { Runner } from '../models/entities/Runner';
import { RunnerOrganisation } from '../models/entities/RunnerOrganisation'; import { RunnerOrganization } from '../models/entities/RunnerOrganization';
import { RunnerTeam } from '../models/entities/RunnerTeam'; import { RunnerTeam } from '../models/entities/RunnerTeam';
import { Scan } from '../models/entities/Scan'; import { Scan } from '../models/entities/Scan';
import { User } from '../models/entities/User'; import { User } from '../models/entities/User';
import { ResponseStats } from '../models/responses/ResponseStats'; import { ResponseStats } from '../models/responses/ResponseStats';
import { ResponseStatsOrgnisation } from '../models/responses/ResponseStatsOrganisation'; import { ResponseStatsOrgnisation } from '../models/responses/ResponseStatsOrganization';
import { ResponseStatsRunner } from '../models/responses/ResponseStatsRunner'; import { ResponseStatsRunner } from '../models/responses/ResponseStatsRunner';
import { ResponseStatsTeam } from '../models/responses/ResponseStatsTeam'; import { ResponseStatsTeam } from '../models/responses/ResponseStatsTeam';
@@ -23,7 +23,7 @@ export class StatsController {
let connection = getConnection(); let connection = getConnection();
let runners = await connection.getRepository(Runner).find({ relations: ['scans', 'scans.track'] }); let runners = await connection.getRepository(Runner).find({ relations: ['scans', 'scans.track'] });
let teams = await connection.getRepository(RunnerTeam).find(); let teams = await connection.getRepository(RunnerTeam).find();
let orgs = await connection.getRepository(RunnerOrganisation).find(); let orgs = await connection.getRepository(RunnerOrganization).find();
let users = await connection.getRepository(User).find(); let users = await connection.getRepository(User).find();
let scans = await connection.getRepository(Scan).find(); let scans = await connection.getRepository(Scan).find();
let donations = await connection.getRepository(Donation).find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] }); let donations = await connection.getRepository(Donation).find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] });
@@ -94,12 +94,12 @@ export class StatsController {
return responseTeams; return responseTeams;
} }
@Get("/organisations/distance") @Get("/organizations/distance")
@UseBefore(StatsAuth) @UseBefore(StatsAuth)
@ResponseSchema(ResponseStatsOrgnisation, { isArray: true }) @ResponseSchema(ResponseStatsOrgnisation, { isArray: true })
@OpenAPI({ description: "Returns the top ten organisations by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten organizations by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopOrgsByDistance() { async getTopOrgsByDistance() {
let orgs = await getConnection().getRepository(RunnerOrganisation).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] }); let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] });
let topOrgs = orgs.sort((org1, org2) => org1.distance - org2.distance).slice(0, 9); let topOrgs = orgs.sort((org1, org2) => org1.distance - org2.distance).slice(0, 9);
let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>(); let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>();
topOrgs.forEach(org => { topOrgs.forEach(org => {
@@ -108,12 +108,12 @@ export class StatsController {
return responseOrgs; return responseOrgs;
} }
@Get("/organisations/donations") @Get("/organizations/donations")
@UseBefore(StatsAuth) @UseBefore(StatsAuth)
@ResponseSchema(ResponseStatsOrgnisation, { isArray: true }) @ResponseSchema(ResponseStatsOrgnisation, { isArray: true })
@OpenAPI({ description: "Returns the top ten organisations by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten organizations by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopOrgsByDonations() { async getTopOrgsByDonations() {
let orgs = await getConnection().getRepository(RunnerOrganisation).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] }); let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] });
let topOrgs = orgs.sort((org1, org2) => org1.distanceDonationAmount - org2.distanceDonationAmount).slice(0, 9); let topOrgs = orgs.sort((org1, org2) => org1.distanceDonationAmount - org2.distanceDonationAmount).slice(0, 9);
let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>(); let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>();
topOrgs.forEach(org => { topOrgs.forEach(org => {

View File

@@ -32,7 +32,18 @@ export class RunnerGroupNeededError extends NotAcceptableError {
name = "RunnerGroupNeededError" name = "RunnerGroupNeededError"
@IsString() @IsString()
message = "Runner's need to be part of one group (team or organisation)! \n You provided neither." message = "Runner's need to be part of one group (team or organization)! \n You provided neither."
}
/**
* Error to throw when a citizen runner has no mail-address.
*/
export class RunnerEmailNeededError extends NotAcceptableError {
@IsString()
name = "RunnerEmailNeededError"
@IsString()
message = "Citizenrunners have to provide an email address for verification and contacting."
} }
/** /**

View File

@@ -1,58 +0,0 @@
import { IsString } from 'class-validator';
import { NotAcceptableError, NotFoundError } from 'routing-controllers';
/**
* Error to throw when a runner organisation couldn't be found.
*/
export class RunnerOrganisationNotFoundError extends NotFoundError {
@IsString()
name = "RunnerOrganisationNotFoundError"
@IsString()
message = "RunnerOrganisation not found!"
}
/**
* Error to throw when two runner organisation's ids don't match.
* Usually occurs when a user tries to change a runner organisation's id.
*/
export class RunnerOrganisationIdsNotMatchingError extends NotAcceptableError {
@IsString()
name = "RunnerOrganisationIdsNotMatchingError"
@IsString()
message = "The ids don't match! \n And if you wanted to change a runner organisation's id: This isn't allowed!"
}
/**
* Error to throw when a organisation still has runners associated.
*/
export class RunnerOrganisationHasRunnersError extends NotAcceptableError {
@IsString()
name = "RunnerOrganisationHasRunnersError"
@IsString()
message = "This organisation still has runners associated with it. \n If you want to delete this organisation with all it's runners and teams add `?force` to your query."
}
/**
* Error to throw when a organisation still has teams associated.
*/
export class RunnerOrganisationHasTeamsError extends NotAcceptableError {
@IsString()
name = "RunnerOrganisationHasTeamsError"
@IsString()
message = "This organisation still has teams associated with it. \n If you want to delete this organisation with all it's runners and teams add `?force` to your query."
}
/**
* Error to throw, when a provided runnerOrganisation doesn't belong to the accepted types.
*/
export class RunnerOrganisationWrongTypeError extends NotAcceptableError {
@IsString()
name = "RunnerOrganisationWrongTypeError"
@IsString()
message = "The runner organisation must be an existing organisation's id. \n You provided a object of another type."
}

View File

@@ -0,0 +1,58 @@
import { IsString } from 'class-validator';
import { NotAcceptableError, NotFoundError } from 'routing-controllers';
/**
* Error to throw when a runner organization couldn't be found.
*/
export class RunnerOrganizationNotFoundError extends NotFoundError {
@IsString()
name = "RunnerOrganizationNotFoundError"
@IsString()
message = "RunnerOrganization not found!"
}
/**
* Error to throw when two runner organization's ids don't match.
* Usually occurs when a user tries to change a runner organization's id.
*/
export class RunnerOrganizationIdsNotMatchingError extends NotAcceptableError {
@IsString()
name = "RunnerOrganizationIdsNotMatchingError"
@IsString()
message = "The ids don't match! \n And if you wanted to change a runner organization's id: This isn't allowed!"
}
/**
* Error to throw when a organization still has runners associated.
*/
export class RunnerOrganizationHasRunnersError extends NotAcceptableError {
@IsString()
name = "RunnerOrganizationHasRunnersError"
@IsString()
message = "This organization still has runners associated with it. \n If you want to delete this organization with all it's runners and teams add `?force` to your query."
}
/**
* Error to throw when a organization still has teams associated.
*/
export class RunnerOrganizationHasTeamsError extends NotAcceptableError {
@IsString()
name = "RunnerOrganizationHasTeamsError"
@IsString()
message = "This organization still has teams associated with it. \n If you want to delete this organization with all it's runners and teams add `?force` to your query."
}
/**
* Error to throw, when a provided runnerOrganization doesn't belong to the accepted types.
*/
export class RunnerOrganizationWrongTypeError extends NotAcceptableError {
@IsString()
name = "RunnerOrganizationWrongTypeError"
@IsString()
message = "The runner organization must be an existing organization's id. \n You provided a object of another type."
}

View File

@@ -43,5 +43,5 @@ export class RunnerTeamNeedsParentError extends NotAcceptableError {
name = "RunnerTeamNeedsParentError" name = "RunnerTeamNeedsParentError"
@IsString() @IsString()
message = "You provided no runner organisation as this team's parent group." message = "You provided no runner organization as this team's parent group."
} }

View File

@@ -1,6 +1,7 @@
import { IsBoolean, IsEmail, IsInt, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator'; import { IsBoolean, IsEmail, IsInt, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
import * as jsonwebtoken from "jsonwebtoken"; import * as jsonwebtoken from "jsonwebtoken";
import { config } from './config'; import { config } from './config';
import { Runner } from './models/entities/Runner';
import { User } from './models/entities/User'; import { User } from './models/entities/User';
/** /**
@@ -34,6 +35,19 @@ export class JwtCreator {
}, config.jwt_secret) }, config.jwt_secret)
} }
/**
* Creates a new selfservice token for a given runner.
* @param runner Runner entity that the access token shall be created for.
* @param expiry_timestamp Timestamp for the token expiry. Will be set about 9999 years if none provided.
*/
public static createSelfService(runner: Runner, expiry_timestamp?: number) {
if (!expiry_timestamp) { expiry_timestamp = Math.floor(Date.now() / 1000) + 36000 * 60 * 24 * 365 * 9999; }
return jsonwebtoken.sign({
id: runner.id,
exp: expiry_timestamp
}, config.jwt_secret)
}
/** /**
* Creates a new password reset token for a given user. * Creates a new password reset token for a given user.
* The token is valid for 15 minutes or 1 use - whatever comes first. * The token is valid for 15 minutes or 1 use - whatever comes first.

View File

@@ -1,6 +1,9 @@
import { createConnection } from "typeorm"; import { createConnection } from "typeorm";
import { runSeeder } from 'typeorm-seeding'; import { runSeeder } from 'typeorm-seeding';
import { User } from '../models/entities/User'; import { config } from '../config';
import { ConfigFlag } from '../models/entities/ConfigFlags';
import SeedPublicOrg from '../seeds/SeedPublicOrg';
import SeedTestRunners from '../seeds/SeedTestRunners';
import SeedUsers from '../seeds/SeedUsers'; import SeedUsers from '../seeds/SeedUsers';
/** /**
* Loader for the database that creates the database connection and initializes the database tabels. * Loader for the database that creates the database connection and initializes the database tabels.
@@ -9,8 +12,20 @@ import SeedUsers from '../seeds/SeedUsers';
export default async () => { export default async () => {
const connection = await createConnection(); const connection = await createConnection();
await connection.synchronize(); await connection.synchronize();
if (await connection.getRepository(User).count() === 0) {
//The data seeding part
if (!(await connection.getRepository(ConfigFlag).findOne({ option: "seeded:user", value: "true" }))) {
await runSeeder(SeedUsers); await runSeeder(SeedUsers);
await connection.getRepository(ConfigFlag).save({ option: "seeded:user", value: "true" });
} }
if (!(await connection.getRepository(ConfigFlag).findOne({ option: "seeded:citizenorg", value: "true" }))) {
await runSeeder(SeedPublicOrg);
await connection.getRepository(ConfigFlag).save({ option: "seeded:citizenorg", value: "true" });
}
if (!(await connection.getRepository(ConfigFlag).findOne({ option: "seeded:testdata", value: "true" })) && config.seedTestData == true) {
await runSeeder(SeedTestRunners);
await connection.getRepository(ConfigFlag).save({ option: "seeded:testdata", value: "true" });
}
return connection; return connection;
}; };

View File

@@ -42,7 +42,7 @@ const StatsAuth = async (req: Request, res: Response, next: () => void) => {
let user_authorized = false; let user_authorized = false;
try { try {
let action = { request: req, response: res, context: null, next: next } let action = { request: req, response: res, context: null, next: next }
user_authorized = await authchecker(action, ["RUNNER:GET", "TEAM:GET", "ORGANISATION:GET"]); user_authorized = await authchecker(action, ["RUNNER:GET", "TEAM:GET", "ORGANIZATION:GET"]);
} }
finally { finally {
if (user_authorized == false) { if (user_authorized == false) {

View File

@@ -1,9 +1,9 @@
import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { RunnerGroupNeededError } from '../../errors/RunnerErrors'; import { RunnerGroupNeededError } from '../../errors/RunnerErrors';
import { RunnerOrganisationNotFoundError } from '../../errors/RunnerOrganisationErrors'; import { RunnerOrganizationNotFoundError } from '../../errors/RunnerOrganizationErrors';
import { RunnerGroup } from '../entities/RunnerGroup'; import { RunnerGroup } from '../entities/RunnerGroup';
import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { RunnerOrganization } from '../entities/RunnerOrganization';
import { RunnerTeam } from '../entities/RunnerTeam'; import { RunnerTeam } from '../entities/RunnerTeam';
import { CreateRunner } from './create/CreateRunner'; import { CreateRunner } from './create/CreateRunner';
@@ -78,9 +78,9 @@ export class ImportRunner {
let team = await getConnectionManager().get().getRepository(RunnerTeam).findOne({ id: groupID }); let team = await getConnectionManager().get().getRepository(RunnerTeam).findOne({ id: groupID });
if (team) { return team; } if (team) { return team; }
let org = await getConnectionManager().get().getRepository(RunnerOrganisation).findOne({ id: groupID }); let org = await getConnectionManager().get().getRepository(RunnerOrganization).findOne({ id: groupID });
if (!org) { if (!org) {
throw new RunnerOrganisationNotFoundError(); throw new RunnerOrganizationNotFoundError();
} }
if (this.team === undefined) { return org; } if (this.team === undefined) { return org; }

View File

@@ -1,7 +1,7 @@
import { IsInt } from 'class-validator'; import { IsInt } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors';
import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; import { RunnerOrganizationWrongTypeError } from '../../../errors/RunnerOrganizationErrors';
import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors';
import { Address } from '../../entities/Address'; import { Address } from '../../entities/Address';
import { Runner } from '../../entities/Runner'; import { Runner } from '../../entities/Runner';
@@ -50,6 +50,6 @@ export class CreateRunner extends CreateParticipant {
return group; return group;
} }
throw new RunnerOrganisationWrongTypeError; throw new RunnerOrganizationWrongTypeError;
} }
} }

View File

@@ -1,30 +0,0 @@
import { IsObject, IsOptional } from 'class-validator';
import { Address } from '../../entities/Address';
import { RunnerOrganisation } from '../../entities/RunnerOrganisation';
import { CreateRunnerGroup } from './CreateRunnerGroup';
/**
* This classed is used to create a new RunnerOrganisation entity from a json body (post request).
*/
export class CreateRunnerOrganisation extends CreateRunnerGroup {
/**
* The new organisation's address.
*/
@IsOptional()
@IsObject()
address?: Address;
/**
* Creates a new RunnerOrganisation entity from this.
*/
public async toEntity(): Promise<RunnerOrganisation> {
let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation();
newRunnerOrganisation.name = this.name;
newRunnerOrganisation.contact = await this.getContact();
newRunnerOrganisation.address = this.address;
Address.validate(newRunnerOrganisation.address);
return newRunnerOrganisation;
}
}

View File

@@ -0,0 +1,43 @@
import { IsBoolean, IsObject, IsOptional } from 'class-validator';
import * as uuid from 'uuid';
import { Address } from '../../entities/Address';
import { RunnerOrganization } from '../../entities/RunnerOrganization';
import { CreateRunnerGroup } from './CreateRunnerGroup';
/**
* This classed is used to create a new RunnerOrganization entity from a json body (post request).
*/
export class CreateRunnerOrganization extends CreateRunnerGroup {
/**
* The new organization's address.
*/
@IsOptional()
@IsObject()
address?: Address;
/**
* Is registration enabled for the new organization?
*/
@IsOptional()
@IsBoolean()
registrationEnabled?: boolean = false;
/**
* Creates a new RunnerOrganization entity from this.
*/
public async toEntity(): Promise<RunnerOrganization> {
let newRunnerOrganization: RunnerOrganization = new RunnerOrganization();
newRunnerOrganization.name = this.name;
newRunnerOrganization.contact = await this.getContact();
newRunnerOrganization.address = this.address;
Address.validate(newRunnerOrganization.address);
if (this.registrationEnabled) {
newRunnerOrganization.key = uuid.v4().toUpperCase();
}
return newRunnerOrganization;
}
}

View File

@@ -1,8 +1,8 @@
import { IsInt, IsNotEmpty } from 'class-validator'; import { IsInt, IsNotEmpty } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { RunnerOrganisationNotFoundError } from '../../../errors/RunnerOrganisationErrors'; import { RunnerOrganizationNotFoundError } from '../../../errors/RunnerOrganizationErrors';
import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors';
import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; import { RunnerOrganization } from '../../entities/RunnerOrganization';
import { RunnerTeam } from '../../entities/RunnerTeam'; import { RunnerTeam } from '../../entities/RunnerTeam';
import { CreateRunnerGroup } from './CreateRunnerGroup'; import { CreateRunnerGroup } from './CreateRunnerGroup';
@@ -21,12 +21,12 @@ export class CreateRunnerTeam extends CreateRunnerGroup {
/** /**
* Gets the new team's parent org based on it's id. * Gets the new team's parent org based on it's id.
*/ */
public async getParent(): Promise<RunnerOrganisation> { public async getParent(): Promise<RunnerOrganization> {
if (this.parentGroup === undefined || this.parentGroup === null) { if (this.parentGroup === undefined || this.parentGroup === null) {
throw new RunnerTeamNeedsParentError(); throw new RunnerTeamNeedsParentError();
} }
let parentGroup = await getConnectionManager().get().getRepository(RunnerOrganisation).findOne({ id: this.parentGroup }); let parentGroup = await getConnectionManager().get().getRepository(RunnerOrganization).findOne({ id: this.parentGroup });
if (!parentGroup) { throw new RunnerOrganisationNotFoundError();; } if (!parentGroup) { throw new RunnerOrganizationNotFoundError();; }
return parentGroup; return parentGroup;
} }

View File

@@ -0,0 +1,52 @@
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { getConnection } from 'typeorm';
import { RunnerEmailNeededError } from '../../../errors/RunnerErrors';
import { Address } from '../../entities/Address';
import { Runner } from '../../entities/Runner';
import { RunnerOrganization } from '../../entities/RunnerOrganization';
import { CreateParticipant } from './CreateParticipant';
/**
* This classed is used to create a new Runner entity from a json body (post request).
*/
export class CreateSelfServiceCitizenRunner extends CreateParticipant {
/**
* The new runners's e-mail address.
* Must be provided for email-verification to work.
*/
@IsString()
@IsNotEmpty()
@IsEmail()
email: string;
/**
* Creates a new Runner entity from this.
*/
public async toEntity(): Promise<Runner> {
let newRunner: Runner = new Runner();
newRunner.firstname = this.firstname;
newRunner.middlename = this.middlename;
newRunner.lastname = this.lastname;
newRunner.phone = this.phone;
newRunner.email = this.email;
if (!newRunner.email) {
throw new RunnerEmailNeededError();
}
newRunner.group = await this.getGroup();
newRunner.address = this.address;
Address.validate(newRunner.address);
return newRunner;
}
/**
* Gets the new runner's group by it's id.
*/
public async getGroup(): Promise<RunnerOrganization> {
return await getConnection().getRepository(RunnerOrganization).findOne({ id: 1 });
}
}

View File

@@ -0,0 +1,55 @@
import { IsInt, IsOptional } from 'class-validator';
import { getConnection } from 'typeorm';
import { RunnerTeamNotFoundError } from '../../../errors/RunnerTeamErrors';
import { Address } from '../../entities/Address';
import { Runner } from '../../entities/Runner';
import { RunnerGroup } from '../../entities/RunnerGroup';
import { RunnerTeam } from '../../entities/RunnerTeam';
import { CreateParticipant } from './CreateParticipant';
/**
* This classed is used to create a new Runner entity from a json body (post request).
*/
export class CreateSelfServiceRunner extends CreateParticipant {
/**
* The new runner's team's id.
* The team has to be a part of the runner's org.
* The team property may get ignored.
* If no team get's provided the runner's group will be their org.
*/
@IsInt()
@IsOptional()
team?: number;
/**
* Creates a new Runner entity from this.
*/
public async toEntity(group: RunnerGroup): Promise<Runner> {
let newRunner: Runner = new Runner();
newRunner.firstname = this.firstname;
newRunner.middlename = this.middlename;
newRunner.lastname = this.lastname;
newRunner.phone = this.phone;
newRunner.email = this.email;
newRunner.group = await this.getGroup(group);
newRunner.address = this.address;
Address.validate(newRunner.address);
return newRunner;
}
/**
* Gets the new runner's group by it's id.
*/
public async getGroup(group: RunnerGroup): Promise<RunnerGroup> {
if (!this.team) {
return group;
}
const team = await getConnection().getRepository(RunnerTeam).findOne({ id: this.team }, { relations: ["parentGroup"] });
if (!team) { throw new RunnerTeamNotFoundError(); }
if (team.parentGroup.id != group.id) { throw new RunnerTeamNotFoundError(); }
return team;
}
}

View File

@@ -1,38 +0,0 @@
import { IsInt, IsObject, IsOptional } from 'class-validator';
import { Address } from '../../entities/Address';
import { RunnerOrganisation } from '../../entities/RunnerOrganisation';
import { CreateRunnerGroup } from '../create/CreateRunnerGroup';
/**
* This class is used to update a RunnerOrganisation entity (via put request).
*/
export class UpdateRunnerOrganisation extends CreateRunnerGroup {
/**
* The updated orgs's id.
* This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
*/
@IsInt()
id: number;
/**
* The updated organisation's address.
*/
@IsOptional()
@IsObject()
address?: Address;
/**
* Updates a provided RunnerOrganisation entity based on this.
*/
public async update(organisation: RunnerOrganisation): Promise<RunnerOrganisation> {
organisation.name = this.name;
organisation.contact = await this.getContact();
if (!this.address) { organisation.address.reset(); }
else { organisation.address = this.address; }
Address.validate(organisation.address);
return organisation;
}
}

View File

@@ -0,0 +1,53 @@
import { IsBoolean, IsInt, IsObject, IsOptional } from 'class-validator';
import * as uuid from 'uuid';
import { Address } from '../../entities/Address';
import { RunnerOrganization } from '../../entities/RunnerOrganization';
import { CreateRunnerGroup } from '../create/CreateRunnerGroup';
/**
* This class is used to update a RunnerOrganization entity (via put request).
*/
export class UpdateRunnerOrganization extends CreateRunnerGroup {
/**
* The updated orgs's id.
* This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
*/
@IsInt()
id: number;
/**
* The updated organization's address.
*/
@IsOptional()
@IsObject()
address?: Address;
/**
* Is registration enabled for the updated organization?
*/
@IsOptional()
@IsBoolean()
registrationEnabled?: boolean = false;
/**
* Updates a provided RunnerOrganization entity based on this.
*/
public async update(organization: RunnerOrganization): Promise<RunnerOrganization> {
organization.name = this.name;
organization.contact = await this.getContact();
if (!this.address) { organization.address.reset(); }
else { organization.address = this.address; }
Address.validate(organization.address);
if (this.registrationEnabled && !organization.key) {
organization.key = uuid.v4().toUpperCase();
}
else {
organization.key = null;
}
return organization;
}
}

View File

@@ -1,8 +1,8 @@
import { IsInt, IsPositive } from 'class-validator'; import { IsInt, IsPositive } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { RunnerOrganisationNotFoundError } from '../../../errors/RunnerOrganisationErrors'; import { RunnerOrganizationNotFoundError } from '../../../errors/RunnerOrganizationErrors';
import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors';
import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; import { RunnerOrganization } from '../../entities/RunnerOrganization';
import { RunnerTeam } from '../../entities/RunnerTeam'; import { RunnerTeam } from '../../entities/RunnerTeam';
import { CreateRunnerGroup } from '../create/CreateRunnerGroup'; import { CreateRunnerGroup } from '../create/CreateRunnerGroup';
@@ -28,12 +28,12 @@ export class UpdateRunnerTeam extends CreateRunnerGroup {
/** /**
* Loads the updated teams's parentGroup based on it's id. * Loads the updated teams's parentGroup based on it's id.
*/ */
public async getParent(): Promise<RunnerOrganisation> { public async getParent(): Promise<RunnerOrganization> {
if (this.parentGroup === undefined || this.parentGroup === null) { if (this.parentGroup === undefined || this.parentGroup === null) {
throw new RunnerTeamNeedsParentError(); throw new RunnerTeamNeedsParentError();
} }
let parentGroup = await getConnectionManager().get().getRepository(RunnerOrganisation).findOne({ id: this.parentGroup }); let parentGroup = await getConnectionManager().get().getRepository(RunnerOrganization).findOne({ id: this.parentGroup });
if (!parentGroup) { throw new RunnerOrganisationNotFoundError();; } if (!parentGroup) { throw new RunnerOrganizationNotFoundError();; }
return parentGroup; return parentGroup;
} }

View File

@@ -0,0 +1,27 @@
import {
IsNotEmpty,
IsString
} from "class-validator";
import { Column, Entity, PrimaryColumn } from "typeorm";
/**
* Defines the ConfigFlag entity.
* This entity can be used to set some flags on db init.
*/
@Entity()
export class ConfigFlag {
/**
* The flag's name (primary).
*/
@PrimaryColumn()
@IsString()
option: string;
/**
* The flag's value.
*/
@Column()
@IsString()
@IsNotEmpty()
value: string;
}

View File

@@ -16,7 +16,7 @@ import { Scan } from "./Scan";
export class Runner extends Participant { export class Runner extends Participant {
/** /**
* The runner's associated group. * The runner's associated group.
* Can be a runner team or organisation. * Can be a runner team or organization.
*/ */
@IsNotEmpty() @IsNotEmpty()
@ManyToOne(() => RunnerGroup, group => group.runners) @ManyToOne(() => RunnerGroup, group => group.runners)
@@ -65,7 +65,7 @@ export class Runner extends Participant {
*/ */
@IsInt() @IsInt()
public get distanceDonationAmount(): number { public get distanceDonationAmount(): number {
return this.distanceDonations.reduce((sum, current) => sum + current.amountPerDistance, 0) * this.distance; return this.distanceDonations.reduce((sum, current) => sum + current.amount, 0);
} }
/** /**

View File

@@ -1,34 +1,44 @@
import { IsInt, IsOptional } from "class-validator"; import { IsInt, IsOptional, IsString } from "class-validator";
import { ChildEntity, Column, OneToMany } from "typeorm"; import { ChildEntity, Column, OneToMany } from "typeorm";
import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation'; import { ResponseRunnerOrganization } from '../responses/ResponseRunnerOrganization';
import { Address } from './Address'; import { Address } from './Address';
import { Runner } from './Runner'; import { Runner } from './Runner';
import { RunnerGroup } from "./RunnerGroup"; import { RunnerGroup } from "./RunnerGroup";
import { RunnerTeam } from "./RunnerTeam"; import { RunnerTeam } from "./RunnerTeam";
/** /**
* Defines the RunnerOrganisation entity. * Defines the RunnerOrganization entity.
* This usually is a school, club or company. * This usually is a school, club or company.
*/ */
@ChildEntity() @ChildEntity()
export class RunnerOrganisation extends RunnerGroup { export class RunnerOrganization extends RunnerGroup {
/** /**
* The organisations's address. * The organizations's address.
*/ */
@IsOptional() @IsOptional()
@Column(type => Address) @Column(type => Address)
address?: Address; address?: Address;
/** /**
* The organisation's teams. * The organization's teams.
* Used to link teams to a organisation. * Used to link teams to a organization.
*/ */
@OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true }) @OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true })
teams: RunnerTeam[]; teams: RunnerTeam[];
/** /**
* Returns all runners associated with this organisation (directly or indirectly via teams). * The organization's api key for self-service registration.
* The api key can be used for the /runners/register/:token endpoint.
* Is has to be base64 encoded if used via the api (to keep url-safety).
*/
@Column({ nullable: true, unique: true })
@IsString()
@IsOptional()
key?: string;
/**
* Returns all runners associated with this organization (directly or indirectly via teams).
*/ */
public get allRunners(): Runner[] { public get allRunners(): Runner[] {
let returnRunners: Runner[] = new Array<Runner>(); let returnRunners: Runner[] = new Array<Runner>();
@@ -58,7 +68,7 @@ export class RunnerOrganisation extends RunnerGroup {
/** /**
* Turns this entity into it's response class. * Turns this entity into it's response class.
*/ */
public toResponse(): ResponseRunnerOrganisation { public toResponse(): ResponseRunnerOrganization {
return new ResponseRunnerOrganisation(this); return new ResponseRunnerOrganization(this);
} }
} }

View File

@@ -2,7 +2,7 @@ import { IsNotEmpty } from "class-validator";
import { ChildEntity, ManyToOne } from "typeorm"; import { ChildEntity, ManyToOne } from "typeorm";
import { ResponseRunnerTeam } from '../responses/ResponseRunnerTeam'; import { ResponseRunnerTeam } from '../responses/ResponseRunnerTeam';
import { RunnerGroup } from "./RunnerGroup"; import { RunnerGroup } from "./RunnerGroup";
import { RunnerOrganisation } from "./RunnerOrganisation"; import { RunnerOrganization } from "./RunnerOrganization";
/** /**
* Defines the RunnerTeam entity. * Defines the RunnerTeam entity.
@@ -13,11 +13,11 @@ export class RunnerTeam extends RunnerGroup {
/** /**
* The team's parent group. * The team's parent group.
* Every team has to be part of a runnerOrganisation - this get's checked on creation and update. * Every team has to be part of a runnerOrganization - this get's checked on creation and update.
*/ */
@IsNotEmpty() @IsNotEmpty()
@ManyToOne(() => RunnerOrganisation, org => org.teams, { nullable: true }) @ManyToOne(() => RunnerOrganization, org => org.teams, { nullable: true })
parentGroup?: RunnerOrganisation; parentGroup?: RunnerOrganization;
/** /**
* Turns this entity into it's response class. * Turns this entity into it's response class.

View File

@@ -3,7 +3,7 @@
*/ */
export enum PermissionTarget { export enum PermissionTarget {
RUNNER = 'RUNNER', RUNNER = 'RUNNER',
ORGANISATION = 'ORGANISATION', ORGANIZATION = 'ORGANIZATION',
TEAM = 'TEAM', TEAM = 'TEAM',
TRACK = 'TRACK', TRACK = 'TRACK',
USER = 'USER', USER = 'USER',

View File

@@ -1,39 +0,0 @@
import {
IsArray,
IsObject,
IsOptional
} from "class-validator";
import { Address } from '../entities/Address';
import { RunnerOrganisation } from '../entities/RunnerOrganisation';
import { RunnerTeam } from '../entities/RunnerTeam';
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
/**
* Defines the runnerOrganisation response.
*/
export class ResponseRunnerOrganisation extends ResponseRunnerGroup {
/**
* The runnerOrganisation's address.
*/
@IsObject()
@IsOptional()
address?: Address;
/**
* The runnerOrganisation associated teams.
*/
@IsArray()
teams: RunnerTeam[];
/**
* Creates a ResponseRunnerOrganisation object from a runnerOrganisation.
* @param org The runnerOrganisation the response shall be build for.
*/
public constructor(org: RunnerOrganisation) {
super(org);
this.address = org.address;
this.teams = org.teams;
}
}

View File

@@ -0,0 +1,62 @@
import {
IsArray,
IsBase64,
IsBoolean,
IsObject,
IsOptional,
IsString
} from "class-validator";
import { Address } from '../entities/Address';
import { RunnerOrganization } from '../entities/RunnerOrganization';
import { RunnerTeam } from '../entities/RunnerTeam';
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
/**
* Defines the runnerOrganization response.
*/
export class ResponseRunnerOrganization extends ResponseRunnerGroup {
/**
* The runnerOrganization's address.
*/
@IsObject()
@IsOptional()
address?: Address;
/**
* The runnerOrganization associated teams.
*/
@IsArray()
teams: RunnerTeam[];
/**
* The organization's registration key.
* If registration is disabled this is null.
*/
@IsString()
@IsOptional()
@IsBase64()
registrationKey?: string;
/**
* Is registration enabled for the organization?
*/
@IsOptional()
@IsBoolean()
registrationEnabled?: boolean = true;
/**
* Creates a ResponseRunnerOrganization object from a runnerOrganization.
* @param org The runnerOrganization the response shall be build for.
*/
public constructor(org: RunnerOrganization) {
super(org);
this.address = org.address;
this.teams = org.teams;
if (!org.key) { this.registrationEnabled = false; }
else { this.registrationKey = Buffer.from(org.key).toString('base64'); }
}
}

View File

@@ -1,7 +1,7 @@
import { IsNotEmpty, IsObject } from "class-validator"; import { IsNotEmpty, IsObject } from "class-validator";
import { RunnerOrganisation } from '../entities/RunnerOrganisation';
import { RunnerTeam } from '../entities/RunnerTeam'; import { RunnerTeam } from '../entities/RunnerTeam';
import { ResponseRunnerGroup } from './ResponseRunnerGroup'; import { ResponseRunnerGroup } from './ResponseRunnerGroup';
import { ResponseRunnerOrganization } from './ResponseRunnerOrganization';
/** /**
* Defines the runnerTeam response. * Defines the runnerTeam response.
@@ -9,11 +9,11 @@ import { ResponseRunnerGroup } from './ResponseRunnerGroup';
export class ResponseRunnerTeam extends ResponseRunnerGroup { export class ResponseRunnerTeam extends ResponseRunnerGroup {
/** /**
* The runnerTeam's parent group (organisation). * The runnerTeam's parent group (organization).
*/ */
@IsObject() @IsObject()
@IsNotEmpty() @IsNotEmpty()
parentGroup: RunnerOrganisation; parentGroup: ResponseRunnerOrganization;
/** /**
* Creates a ResponseRunnerTeam object from a runnerTeam. * Creates a ResponseRunnerTeam object from a runnerTeam.
@@ -21,6 +21,6 @@ export class ResponseRunnerTeam extends ResponseRunnerGroup {
*/ */
public constructor(team: RunnerTeam) { public constructor(team: RunnerTeam) {
super(team); super(team);
this.parentGroup = team.parentGroup; this.parentGroup = team.parentGroup.toResponse();
} }
} }

View File

@@ -0,0 +1,36 @@
import { IsInt, IsNotEmpty, IsPositive } from 'class-validator';
import { DistanceDonation } from '../entities/DistanceDonation';
/**
* Defines the runner selfservice donation response.
* Why? B/C runner's are not allowed to view all information available to admin users.
*/
export class ResponseSelfServiceDonation {
/**
* The donation's donor.
*/
@IsNotEmpty()
donor: string;
/**
* The donation's amount in the smalles unit of your currency (default: euro cent).
*/
@IsInt()
amount: number;
/**
* The donation's amount donated per distance.
* The amount the donor set to be donated per kilometer that the runner ran.
*/
@IsInt()
@IsPositive()
amountPerDistance: number;
public constructor(donation: DistanceDonation) {
if (!donation.donor.middlename) { this.donor = donation.donor.firstname + " " + donation.donor.lastname; }
else { this.donor = donation.donor.firstname + " " + donation.donor.middlename + " " + donation.donor.lastname; }
this.amountPerDistance = donation.amountPerDistance;
this.amount = donation.amount;
}
}

View File

@@ -0,0 +1,83 @@
import { IsInt, IsOptional, IsString } from "class-validator";
import { DistanceDonation } from '../entities/DistanceDonation';
import { Runner } from '../entities/Runner';
import { RunnerGroup } from '../entities/RunnerGroup';
import { RunnerTeam } from '../entities/RunnerTeam';
import { ResponseParticipant } from './ResponseParticipant';
import { ResponseSelfServiceDonation } from './ResponseSelfServiceDonation';
/**
* Defines the runner selfservice response.
* Why? B/C runner's are not allowed to view all information available to admin users.
*/
export class ResponseSelfServiceRunner extends ResponseParticipant {
/**
* The runner's currently ran distance in meters.
*/
@IsInt()
distance: number;
/**
* The runner's currently collected donations.
*/
@IsInt()
donationAmount: number;
/**
* The runner's group as a string (mix of org and team).
*/
@IsString()
group: string;
/**
* The runner's associated donations.
*/
@IsString()
donations: ResponseSelfServiceDonation[]
/**
* The runner's self-service jwt for auth.
* Will only get delivered on registration/via email.
*/
@IsString()
@IsOptional()
token: string;
/**
* Creates a ResponseRunner object from a runner.
* @param runner The user the response shall be build for.
*/
public constructor(runner: Runner) {
super(runner);
this.distance = runner.distance;
this.donationAmount = runner.distanceDonationAmount;
this.group = this.getTeamString(runner.group);
this.donations = this.getDonations(runner.distanceDonations);
}
/**
* Parses a runner's group into a string.
* If the runner's group is a team: `org name/team name`
* If the runner's group is an org: `org name`
* @param group The group that shall get parsed to a string.
*/
private getTeamString(group: RunnerGroup): string {
if (group instanceof RunnerTeam) {
return group.parentGroup.name + "/" + group.name;
}
return group.name;
}
/**
* Converts all of the runner's donations to ResponseSelfServiceDonations.
* @param donations The donations that shall be converted to ResponseSelfServiceDonations.
*/
private getDonations(donations: DistanceDonation[]): ResponseSelfServiceDonation[] {
let responseDonations = new Array<ResponseSelfServiceDonation>();
for (let donation of donations) {
responseDonations.push(new ResponseSelfServiceDonation(donation));
}
return responseDonations;
}
}

View File

@@ -3,7 +3,7 @@ import {
} from "class-validator"; } from "class-validator";
import { Donation } from '../entities/Donation'; import { Donation } from '../entities/Donation';
import { Runner } from '../entities/Runner'; import { Runner } from '../entities/Runner';
import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { RunnerOrganization } from '../entities/RunnerOrganization';
import { RunnerTeam } from '../entities/RunnerTeam'; import { RunnerTeam } from '../entities/RunnerTeam';
import { Scan } from '../entities/Scan'; import { Scan } from '../entities/Scan';
import { User } from '../entities/User'; import { User } from '../entities/User';
@@ -26,7 +26,7 @@ export class ResponseStats {
total_teams: number; total_teams: number;
/** /**
* The amount of organisations registered in the system. * The amount of organizations registered in the system.
*/ */
@IsInt() @IsInt()
total_orgs: number; total_orgs: number;
@@ -70,7 +70,7 @@ export class ResponseStats {
* @param scans Array containing all scans - no relations have to be resolved. * @param scans Array containing all scans - no relations have to be resolved.
* @param donations Array containing all donations - the following relations have to be resolved: runner, runner.scans, runner.scans.track * @param donations Array containing all donations - the following relations have to be resolved: runner, runner.scans, runner.scans.track
*/ */
public constructor(runners: Runner[], teams: RunnerTeam[], orgs: RunnerOrganisation[], users: User[], scans: Scan[], donations: Donation[]) { public constructor(runners: Runner[], teams: RunnerTeam[], orgs: RunnerOrganization[], users: User[], scans: Scan[], donations: Donation[]) {
this.total_runners = runners.length; this.total_runners = runners.length;
this.total_teams = teams.length; this.total_teams = teams.length;
this.total_orgs = orgs.length; this.total_orgs = orgs.length;

View File

@@ -3,7 +3,7 @@ import {
IsString IsString
} from "class-validator"; } from "class-validator";
import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { RunnerOrganization } from '../entities/RunnerOrganization';
/** /**
* Defines the org stats response. * Defines the org stats response.
@@ -35,10 +35,10 @@ export class ResponseStatsOrgnisation {
donationAmount: number; donationAmount: number;
/** /**
* Creates a new organisation stats response from a organisation * Creates a new organization stats response from a organization
* @param org The organisation whoes response shall be generated - the following relations have to be resolved: runners, runners.scans, runners.distanceDonations, runners.scans.track, teams, teams.runners, teams.runners.scans, teams.runners.distanceDonations, teams.runners.scans.track * @param org The organization whoes response shall be generated - the following relations have to be resolved: runners, runners.scans, runners.distanceDonations, runners.scans.track, teams, teams.runners, teams.runners.scans, teams.runners.distanceDonations, teams.runners.scans.track
*/ */
public constructor(org: RunnerOrganisation) { public constructor(org: RunnerOrganization) {
this.name = org.name; this.name = org.name;
this.id = org.id; this.id = org.id;
this.distance = org.distance; this.distance = org.distance;

View File

@@ -0,0 +1,15 @@
import { Connection } from 'typeorm';
import { Factory, Seeder } from 'typeorm-seeding';
import { CreateRunnerOrganization } from '../models/actions/create/CreateRunnerOrganization';
import { RunnerOrganization } from '../models/entities/RunnerOrganization';
/**
* Seeds the public runner org (named: "Citizen" by default).
*/
export default class SeedPublicOrg implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<any> {
let publicOrg = new CreateRunnerOrganization();
publicOrg.name = "Citizen";
await connection.getRepository(RunnerOrganization).save(await publicOrg.toEntity());
}
}

View File

@@ -0,0 +1,93 @@
import { Connection } from 'typeorm';
import { Factory, Seeder } from 'typeorm-seeding';
import { CreateGroupContact } from '../models/actions/create/CreateGroupContact';
import { CreateRunner } from '../models/actions/create/CreateRunner';
import { CreateRunnerOrganization } from '../models/actions/create/CreateRunnerOrganization';
import { CreateRunnerTeam } from '../models/actions/create/CreateRunnerTeam';
import { Address } from '../models/entities/Address';
import { GroupContact } from '../models/entities/GroupContact';
import { Runner } from '../models/entities/Runner';
import { RunnerGroup } from '../models/entities/RunnerGroup';
import { RunnerOrganization } from '../models/entities/RunnerOrganization';
import { RunnerTeam } from '../models/entities/RunnerTeam';
/**
* Seeds a test runner org with a test runner team ans some test runners.
* Usefull for testing or demo instances.
*/
export default class SeedTestRunners implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<any> {
let testOrg: RunnerOrganization = await this.createTestOrg(connection);
let testTeam: RunnerTeam = await this.createTestTeam(connection, testOrg);
await this.createTestContact(connection, testOrg);
await this.createTestRunners(connection, testOrg);
await this.createTestRunners(connection, testTeam);
}
public async createTestOrg(connection: Connection): Promise<RunnerOrganization> {
let testOrg = new CreateRunnerOrganization();
testOrg.name = "Test Org";
testOrg.address = new Address();
testOrg.address.address1 = "Test street 1";
testOrg.address.city = "Herzogenaurach";
testOrg.address.country = "Germany";
testOrg.address.postalcode = "90174";
return await connection.getRepository(RunnerOrganization).save(await testOrg.toEntity());
}
public async createTestTeam(connection: Connection, org: RunnerOrganization): Promise<RunnerTeam> {
let testTeam = new CreateRunnerTeam();
testTeam.name = "Test Team";
testTeam.parentGroup = org.id;
return await connection.getRepository(RunnerTeam).save(await testTeam.toEntity());
}
public async createTestRunners(connection: Connection, group: RunnerGroup) {
for (let first of this.firstnames) {
for (let last of this.lastnames) {
let runner = new CreateRunner;
runner.firstname = first;
runner.lastname = last;
runner.middlename = group.name;
runner.group = group.id;
await connection.getRepository(Runner).save(await runner.toEntity());
}
}
}
public async createTestContact(connection: Connection, group: RunnerGroup) {
let contact = new CreateGroupContact;
contact.firstname = "Test";
contact.lastname = "Contact";
contact.email = "test.contact@dev.lauf-fuer-kaya.de";
contact.groups = group.id;
contact.address = new Address();
contact.address.address1 = "First Contact Street 100";
contact.address.city = "Herzogenaurach";
contact.address.country = "Germany";
contact.address.postalcode = "90174";
await connection.getRepository(GroupContact).save(await contact.toEntity());
}
private firstnames = [
"Peter",
"Matze",
"Tine",
"Uta",
"Fabian",
"Unicode:ÖÄ?✔⚠"
]
private lastnames = [
"Muster",
"Example",
"Müller",
"Unicode:搆Ǩ>ÙՠƳ|"
]
}

View File

@@ -69,7 +69,7 @@ describe('POST /api/cards successfully (with runner)', () => {
let added_org; let added_org;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -50,7 +50,7 @@ describe('adding + updating card.runner successfully', () => {
let added_runner2; let added_runner2;
let added_card; let added_card;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -108,7 +108,7 @@ describe('POST /api/contacts working (with group)', () => {
let added_team; let added_team;
let added_contact; let added_contact;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;
@@ -123,7 +123,6 @@ describe('POST /api/contacts working (with group)', () => {
"parentGroup": added_org.id "parentGroup": added_org.id
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;
delete res.data.parentGroup;
added_team = res.data; added_team = res.data;
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")

View File

@@ -50,7 +50,7 @@ describe('add+delete (with org)', () => {
let added_org; let added_org;
let added_contact; let added_contact;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;
@@ -88,7 +88,7 @@ describe('add+delete (with team)', () => {
let added_team; let added_team;
let added_contact; let added_contact;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;
@@ -137,7 +137,7 @@ describe('add+delete (with org&team)', () => {
let added_team; let added_team;
let added_contact; let added_contact;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;

View File

@@ -59,7 +59,7 @@ describe('Update contact group after adding (should work)', () => {
let added_team; let added_team;
let added_contact; let added_contact;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;
@@ -74,7 +74,6 @@ describe('Update contact group after adding (should work)', () => {
"parentGroup": added_org.id "parentGroup": added_org.id
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;
delete res.data.parentGroup;
added_team = res.data; added_team = res.data;
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
@@ -112,6 +111,7 @@ describe('Update contact group after adding (should work)', () => {
"lastname": "last", "lastname": "last",
"groups": added_team.id "groups": added_team.id
}, axios_config); }, axios_config);
console.log(res.data)
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({ expect(res.data).toEqual({
@@ -189,7 +189,7 @@ describe('Update contact group invalid after adding (should fail)', () => {
let added_org; let added_org;
let added_contact; let added_contact;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res.data.contact; delete res.data.contact;

View File

@@ -83,7 +83,7 @@ describe('POST /api/donations/distance illegally', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -199,7 +199,7 @@ describe('POST /api/donations/distance successfully', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data

View File

@@ -70,7 +70,7 @@ describe('DELETE distance donation', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data

View File

@@ -73,7 +73,7 @@ describe('adding + getting distance donation', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data

View File

@@ -84,7 +84,7 @@ describe('adding + updating distance donation illegally', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -253,7 +253,7 @@ describe('adding + updating distance donation valid', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data

View File

@@ -60,7 +60,7 @@ describe('DELETE donor with donations invalid', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -115,7 +115,7 @@ describe('DELETE donor with donations valid', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data

View File

@@ -14,24 +14,24 @@ beforeAll(async () => {
}; };
}); });
describe('GET /api/organisations', () => { describe('GET /api/organizations', () => {
it('basic get should return 200', async () => { it('basic get should return 200', async () => {
const res = await axios.get(base + '/api/organisations', axios_config); const res = await axios.get(base + '/api/organizations', axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
}); });
// --------------- // ---------------
describe('POST /api/organisations', () => { describe('POST /api/organizations', () => {
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with without a name should return 400', async () => { it('creating a new org with without a name should return 400', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": null "name": null
}, axios_config); }, axios_config);
expect(res.status).toEqual(400); expect(res.status).toEqual(400);
@@ -41,14 +41,14 @@ describe('POST /api/organisations', () => {
// --------------- // ---------------
describe('adding + getting from all orgs', () => { describe('adding + getting from all orgs', () => {
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('check if org was added', async () => { it('check if org was added', async () => {
const res = await axios.get(base + '/api/organisations', axios_config); const res = await axios.get(base + '/api/organizations', axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
let added_org = res.data[res.data.length - 1] let added_org = res.data[res.data.length - 1]
@@ -63,6 +63,7 @@ describe('adding + getting from all orgs', () => {
"country": null, "country": null,
"postalcode": null, "postalcode": null,
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}) })
}); });
@@ -71,7 +72,7 @@ describe('adding + getting from all orgs', () => {
describe('adding + getting explicitly', () => { describe('adding + getting explicitly', () => {
let added_org_id let added_org_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res1.data
@@ -80,7 +81,7 @@ describe('adding + getting explicitly', () => {
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('check if org was added', async () => { it('check if org was added', async () => {
const res2 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); const res2 = await axios.get(base + '/api/organizations/' + added_org_id, axios_config);
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
let added_org2 = res2.data let added_org2 = res2.data
@@ -96,6 +97,7 @@ describe('adding + getting explicitly', () => {
"country": null, "country": null,
"postalcode": null, "postalcode": null,
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}) })
}); });

View File

@@ -17,7 +17,7 @@ beforeAll(async () => {
// --------------- // ---------------
describe('adding + deletion (non-existant)', () => { describe('adding + deletion (non-existant)', () => {
it('delete', async () => { it('delete', async () => {
const res2 = await axios.delete(base + '/api/organisations/0', axios_config); const res2 = await axios.delete(base + '/api/organizations/0', axios_config);
expect(res2.status).toEqual(204); expect(res2.status).toEqual(204);
}); });
}); });
@@ -26,7 +26,7 @@ describe('adding + deletion (successfull)', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -35,7 +35,7 @@ describe('adding + deletion (successfull)', () => {
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('delete', async () => { it('delete', async () => {
const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); const res2 = await axios.delete(base + '/api/organizations/' + added_org_id, axios_config);
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
let added_org2 = res2.data let added_org2 = res2.data
@@ -51,11 +51,12 @@ describe('adding + deletion (successfull)', () => {
"country": null, "country": null,
"postalcode": null, "postalcode": null,
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('check if org really was deleted', async () => { it('check if org really was deleted', async () => {
const res3 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); const res3 = await axios.get(base + '/api/organizations/' + added_org_id, axios_config);
expect(res3.status).toEqual(404); expect(res3.status).toEqual(404);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });
@@ -67,7 +68,7 @@ describe('adding + deletion with teams still existing (without force)', () => {
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
@@ -86,7 +87,7 @@ describe('adding + deletion with teams still existing (without force)', () => {
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('delete org - this should fail with a 406', async () => { it('delete org - this should fail with a 406', async () => {
const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); const res2 = await axios.delete(base + '/api/organizations/' + added_org_id, axios_config);
expect(res2.status).toEqual(406); expect(res2.status).toEqual(406);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
@@ -98,7 +99,7 @@ describe('adding + deletion with teams still existing (with force)', () => {
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
@@ -117,7 +118,7 @@ describe('adding + deletion with teams still existing (with force)', () => {
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('delete', async () => { it('delete', async () => {
const res2 = await axios.delete(base + '/api/organisations/' + added_org_id + '?force=true', axios_config); const res2 = await axios.delete(base + '/api/organizations/' + added_org_id + '?force=true', axios_config);
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
let added_org2 = res2.data let added_org2 = res2.data
@@ -134,10 +135,11 @@ describe('adding + deletion with teams still existing (with force)', () => {
"country": null, "country": null,
"postalcode": null, "postalcode": null,
}, },
"registrationEnabled": false,
}); });
}); });
it('check if org really was deleted', async () => { it('check if org really was deleted', async () => {
const res3 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); const res3 = await axios.get(base + '/api/organizations/' + added_org_id, axios_config);
expect(res3.status).toEqual(404); expect(res3.status).toEqual(404);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });

View File

@@ -14,15 +14,15 @@ beforeAll(async () => {
}; };
}); });
describe('GET /api/organisations', () => { describe('GET /api/organizations', () => {
it('basic get should return 200', async () => { it('basic get should return 200', async () => {
const res = await axios.get(base + '/api/organisations', axios_config); const res = await axios.get(base + '/api/organizations', axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
}); });
// --------------- // ---------------
describe('GET /api/organisations/0', () => { describe('GET /api/organizations/0', () => {
it('basic get should return 404', async () => { it('basic get should return 404', async () => {
const res = await axios.get(base + '/api/runners/0', axios_config); const res = await axios.get(base + '/api/runners/0', axios_config);
expect(res.status).toEqual(404); expect(res.status).toEqual(404);

View File

@@ -19,7 +19,7 @@ describe('adding + updating name', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -28,7 +28,7 @@ describe('adding + updating name', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('update org', async () => { it('update org', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -49,6 +49,7 @@ describe('adding + updating name', () => {
"country": null, "country": null,
"postalcode": null, "postalcode": null,
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}) })
}); });
@@ -58,7 +59,7 @@ describe('adding + try updating id (should return 406)', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -67,7 +68,7 @@ describe('adding + try updating id (should return 406)', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('update org', async () => { it('update org', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id + 1, "id": added_org_id + 1,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -82,7 +83,7 @@ describe('adding + updateing address valid)', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -91,7 +92,7 @@ describe('adding + updateing address valid)', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('adding address to org should return 200', async () => { it('adding address to org should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -116,11 +117,12 @@ describe('adding + updateing address valid)', () => {
"country": "Burkina Faso", "country": "Burkina Faso",
"postalcode": "90174" "postalcode": "90174"
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('updateing address\'s first line should return 200', async () => { it('updateing address\'s first line should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -145,11 +147,12 @@ describe('adding + updateing address valid)', () => {
"country": "Burkina Faso", "country": "Burkina Faso",
"postalcode": "90174" "postalcode": "90174"
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('updateing address\'s second line should return 200', async () => { it('updateing address\'s second line should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -174,11 +177,12 @@ describe('adding + updateing address valid)', () => {
"country": "Burkina Faso", "country": "Burkina Faso",
"postalcode": "90174" "postalcode": "90174"
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('updateing address\'s city should return 200', async () => { it('updateing address\'s city should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -203,11 +207,12 @@ describe('adding + updateing address valid)', () => {
"country": "Burkina Faso", "country": "Burkina Faso",
"postalcode": "90174" "postalcode": "90174"
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('updateing address\'s country should return 200', async () => { it('updateing address\'s country should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -232,11 +237,12 @@ describe('adding + updateing address valid)', () => {
"country": "Germany", "country": "Germany",
"postalcode": "90174" "postalcode": "90174"
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('updateing address\'s postal code should return 200', async () => { it('updateing address\'s postal code should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -261,14 +267,15 @@ describe('adding + updateing address valid)', () => {
"country": "Germany", "country": "Germany",
"postalcode": "91065" "postalcode": "91065"
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
it('removing org\'s should return 200', async () => { it('removing org\'s address should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null "contact": null,
}, axios_config); }, axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
@@ -283,6 +290,7 @@ describe('adding + updateing address valid)', () => {
"country": null, "country": null,
"postalcode": null "postalcode": null
}, },
"registrationEnabled": false,
"teams": [] "teams": []
}); });
}); });
@@ -292,7 +300,7 @@ describe('adding + updateing address invalid)', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -301,7 +309,7 @@ describe('adding + updateing address invalid)', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('adding address to org w/o address1 should return 400', async () => { it('adding address to org w/o address1 should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -317,7 +325,7 @@ describe('adding + updateing address invalid)', () => {
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
}); });
it('adding address to org w/o city should return 400', async () => { it('adding address to org w/o city should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -333,7 +341,7 @@ describe('adding + updateing address invalid)', () => {
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
}); });
it('adding address to org w/o country should return 400', async () => { it('adding address to org w/o country should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -349,7 +357,7 @@ describe('adding + updateing address invalid)', () => {
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
}); });
it('adding address to org w/o postal code should return 400', async () => { it('adding address to org w/o postal code should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
@@ -365,7 +373,7 @@ describe('adding + updateing address invalid)', () => {
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
}); });
it('adding address to org w/ invalid postal code should return 400', async () => { it('adding address to org w/ invalid postal code should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organizations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,

View File

@@ -58,7 +58,7 @@ describe('POST /api/teams with errors', () => {
describe('POST /api/teams working', () => { describe('POST /api/teams working', () => {
let added_org_id; let added_org_id;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res1.data

View File

@@ -21,7 +21,7 @@ describe('adding org', () => {
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;

View File

@@ -20,7 +20,7 @@ describe('adding + updating name', () => {
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
@@ -59,7 +59,7 @@ describe('adding + try updating id (should return 406)', () => {
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
@@ -92,7 +92,7 @@ describe('add+update parent org (valid)', () => {
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
@@ -110,7 +110,7 @@ describe('add+update parent org (valid)', () => {
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res3 = await axios.post(base + '/api/organisations', { const res3 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org2 = res3.data; added_org2 = res3.data;
@@ -120,11 +120,13 @@ describe('add+update parent org (valid)', () => {
it('update team', async () => { it('update team', async () => {
added_team.parentGroup = added_org2.id; added_team.parentGroup = added_org2.id;
const res4 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); const res4 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config);
let updated_team = res4.data;
expect(res4.status).toEqual(200); expect(res4.status).toEqual(200);
expect(res4.headers['content-type']).toContain("application/json") expect(res4.headers['content-type']).toContain("application/json")
delete added_org2.contact; delete added_org2.contact;
delete added_org2.teams; delete added_org2.teams;
expect(updated_team.parentGroup).toEqual(added_org2) delete added_org2.registrationEnabled;
delete res4.data.parentGroup.key;
delete res4.data.parentGroup.registrationEnabled;
expect(res4.data.parentGroup).toEqual(added_org2)
}); });
}); });

View File

@@ -80,7 +80,7 @@ describe('POST /api/runners with errors', () => {
describe('POST /api/runners working', () => { describe('POST /api/runners working', () => {
let added_org_id; let added_org_id;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res1.data

View File

@@ -25,7 +25,7 @@ describe('add+delete', () => {
let added_org_id; let added_org_id;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res1.data
@@ -71,7 +71,7 @@ describe('DELETE donor with donations invalid', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data
@@ -118,7 +118,7 @@ describe('DELETE donor with donations valid', () => {
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res.data added_org = res.data

View File

@@ -33,36 +33,106 @@ describe('GET /api/runners after adding', () => {
let added_org_id; let added_org_id;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res.data
added_org_id = added_org.id; added_org_id = added_org.id;
expect(res1.status).toEqual(200); expect(res.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new runner with only needed params should return 200', async () => { it('creating a new runner with only needed params should return 200', async () => {
const res2 = await axios.post(base + '/api/runners', { const res = await axios.post(base + '/api/runners', {
"firstname": "first", "firstname": "first",
"lastname": "last", "lastname": "last",
"group": added_org_id "group": added_org_id
}, axios_config); }, axios_config);
added_runner = res2.data; added_runner = res.data;
expect(res2.status).toEqual(200); expect(res.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('explicit get should return 200', async () => { it('explicit get should return 200', async () => {
const res3 = await axios.get(base + '/api/runners/' + added_runner.id, axios_config); const res = await axios.get(base + '/api/runners/' + added_runner.id, axios_config);
expect(res3.status).toEqual(200); expect(res.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
let gotten_runner = res3.data let gotten_runner = res.data
expect(gotten_runner).toEqual(added_runner); expect(gotten_runner).toEqual(added_runner);
}); });
it('get from all runners should return 200', async () => { it('get from all runners should return 200', async () => {
const res4 = await axios.get(base + '/api/runners/', axios_config); const res = await axios.get(base + '/api/runners/', axios_config);
expect(res4.status).toEqual(200); expect(res.status).toEqual(200);
expect(res4.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
let gotten_runners = res4.data let gotten_runners = res.data
expect(gotten_runners).toContainEqual(added_runner); expect(gotten_runners).toContainEqual(added_runner);
}); });
}); });
// ---------------
describe('GET /api/organizations/:id/runners after adding', () => {
let added_org_id;
let added_runner;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organizations', {
"name": "test123"
}, axios_config);
let added_org = res.data
added_org_id = added_org.id;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new runner with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/runners', {
"firstname": "first",
"lastname": "last",
"group": added_org_id
}, axios_config);
added_runner = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('check if scans was added via the orgs/runners endpoint.', async () => {
const res = await axios.get(base + '/api/organizations/' + added_org_id + "/runners", axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toContainEqual(added_runner);
});
});
// ---------------
describe('GET /api/teams/:id/runners after adding', () => {
let added_org_id;
let added_team;
let added_runner;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organizations', {
"name": "test123"
}, axios_config);
let added_org = res.data
added_org_id = added_org.id;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new team with a parent org should return 200', async () => {
const res = await axios.post(base + '/api/teams', {
"name": "test_team",
"parentGroup": added_org_id
}, axios_config);
added_team = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new runner with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/runners', {
"firstname": "first",
"lastname": "last",
"group": added_team.id
}, axios_config);
added_runner = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('check if scans was added via the orgs/runners endpoint.', async () => {
const res = await axios.get(base + '/api/teams/' + added_team.id + "/runners", axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toContainEqual(added_runner);
});
});

View File

@@ -17,11 +17,11 @@ beforeAll(async () => {
describe('Update runner name after adding', () => { describe('Update runner name after adding', () => {
let added_org; let added_org;
let added_runner; let added_runner;
let updated_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
delete res1.data.registrationEnabled;
added_org = res1.data added_org = res1.data
expect(res1.status).toEqual(200); expect(res1.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
@@ -43,11 +43,13 @@ describe('Update runner name after adding', () => {
const res3 = await axios.put(base + '/api/runners/' + added_runner.id, runnercopy, axios_config); const res3 = await axios.put(base + '/api/runners/' + added_runner.id, runnercopy, axios_config);
expect(res3.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
updated_runner = res3.data;
delete added_org.contact; delete added_org.contact;
delete added_org.teams; delete added_org.teams;
runnercopy.group = added_org; runnercopy.group = added_org;
expect(updated_runner).toEqual(runnercopy); delete res3.data.group.key;
delete res3.data.group.registrationEnabled;
delete runnercopy.group.registrationEnabled;
expect(res3.data).toEqual(runnercopy);
}); });
}); });
// --------------- // ---------------
@@ -56,7 +58,7 @@ describe('Update runner group after adding', () => {
let added_org_2; let added_org_2;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res1.data
@@ -75,7 +77,7 @@ describe('Update runner group after adding', () => {
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res3 = await axios.post(base + '/api/organisations', { const res3 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org_2 = res3.data added_org_2 = res3.data
@@ -86,9 +88,12 @@ describe('Update runner group after adding', () => {
}); });
it('valid group update should return 200', async () => { it('valid group update should return 200', async () => {
added_runner.group = added_org_2.id; added_runner.group = added_org_2.id;
delete added_org_2.registrationEnabled;
const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config); const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config);
expect(res3.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
delete res3.data.group.key;
delete res3.data.group.registrationEnabled;
expect(res3.data.group).toEqual(added_org_2); expect(res3.data.group).toEqual(added_org_2);
}); });
}); });
@@ -98,7 +103,7 @@ describe('Update runner id after adding(should fail)', () => {
let added_runner; let added_runner;
let added_runner_id; let added_runner_id;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
let added_org = res1.data let added_org = res1.data
@@ -130,7 +135,7 @@ describe('Update runner group with invalid group after adding', () => {
let added_org; let added_org;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -19,7 +19,7 @@ describe('POST /api/scans illegally', () => {
let added_org; let added_org;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -70,7 +70,7 @@ describe('POST /api/scans successfully', () => {
let added_org; let added_org;
let added_runner; let added_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -144,7 +144,7 @@ describe('POST /api/scans successfully via scan station', () => {
let added_track; let added_track;
let added_station; let added_station;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -21,7 +21,7 @@ describe('DELETE scan', () => {
let added_runner; let added_runner;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -35,7 +35,7 @@ describe('adding + getting scans', () => {
let added_runner; let added_runner;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -61,9 +61,17 @@ describe('adding + getting scans', () => {
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('check if scans was added (no parameter validation)', async () => { it('check if scans was added directly', async () => {
const res = await axios.get(base + '/api/scans/' + added_scan.id, axios_config); const res = await axios.get(base + '/api/scans/' + added_scan.id, axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual(added_scan);
});
it('check if scans was added via the runner/scans endpoint.', async () => {
const res = await axios.get(base + '/api/runners/' + added_runner.id + "/scans", axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
added_scan.runner.distance = 0;
expect(res.data).toContainEqual(added_scan);
}); });
}); });

View File

@@ -19,7 +19,7 @@ describe('adding + updating illegally', () => {
let added_runner; let added_runner;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -86,7 +86,7 @@ describe('adding + updating successfilly', () => {
let added_runner2; let added_runner2;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -0,0 +1,43 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let access_token;
let axios_config;
beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"];
axios_config = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
describe('GET /api/runners/me invalid should return fail', () => {
it('get with invalid jwt should return 401', async () => {
const res = await axios.get(base + '/api/runners/me/123.123', axios_config);
expect(res.status).toEqual(401);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('register + get should return 200', () => {
let added_runner;
it('registering as citizen should return 200', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "user@example.com"
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
added_runner = res.data;
});
it('get with valid jwt should return 200', async () => {
const res = await axios.get(base + '/api/runners/me/' + added_runner.token, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});

View File

@@ -0,0 +1,248 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let access_token;
let axios_config;
beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"];
axios_config = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
describe('register invalid citizen', () => {
it('registering as citizen without mail should return 406', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
}, axios_config);
expect(res.status).toEqual(406);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering as citizen with invalid mail should return 400', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "user"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering as citizen without fist name should return 400', async () => {
const res = await axios.post(base + '/api/runners/register', {
"middlename": "string",
"lastname": "string",
"email": "user@example.com"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering as citizen without last name should return 400', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"middlename": "string",
"email": "user@example.com"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering as citizen with invalid mail should return 400', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"phone": "peter",
"email": "user@example.com"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('register citizen valid', () => {
it('registering as citizen with minimal params should return 200', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"lastname": "string",
"email": "user@example.com"
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering as citizen with all params should return 200', async () => {
const res = await axios.post(base + '/api/runners/register', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "user@example.com",
"phone": "+4909132123456",
"address": {
address1: "Teststreet 1",
address2: "Testapartement",
postalcode: "91074",
city: "Herzo",
country: "Germany"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('register invalid company', () => {
let added_org;
it('creating a new org with just a name and registration enabled should return 200', async () => {
const res = await axios.post(base + '/api/organizations', {
"name": "test123",
"registrationEnabled": true
}, axios_config);
added_org = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('registering with bs token should return 404', async () => {
const res = await axios.post(base + '/api/runners/register/4040404', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
}, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering without firstname should return 400', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"middlename": "string",
"lastname": "string",
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering without lastname should return 400', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"middlename": "string",
"firstname": "string",
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering with bs mail should return 400', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "true"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering with invalid team should return 404', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"lastname": "string",
"team": 9999999999999999999999
}, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('register valid company', () => {
let added_org;
let added_team;
it('creating a new org with just a name and registration enabled should return 200', async () => {
const res = await axios.post(base + '/api/organizations', {
"name": "test123",
"registrationEnabled": true
}, axios_config);
added_org = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new team with a parent org should return 200', async () => {
const res = await axios.post(base + '/api/teams', {
"name": "test_team",
"parentGroup": added_org.id
}, axios_config);
added_team = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('registering with minimal params should return 200', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"lastname": "string",
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering with all params except team should return 200', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "user@example.com",
"phone": "+4909132123456",
"address": {
address1: "Teststreet 1",
address2: "Testapartement",
postalcode: "91074",
city: "Herzo",
country: "Germany"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering with minimal params and team should return 200', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"lastname": "string",
"team": added_team.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering with all params except team should return 200', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "user@example.com",
"phone": "+4909132123456",
"address": {
address1: "Teststreet 1",
address2: "Testapartement",
postalcode: "91074",
city: "Herzo",
country: "Germany"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('registering with all params and team should return 200', async () => {
const res = await axios.post(base + '/api/runners/register/' + added_org.registrationKey, {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"email": "user@example.com",
"phone": "+4909132123456",
"address": {
address1: "Teststreet 1",
address2: "Testapartement",
postalcode: "91074",
city: "Herzo",
country: "Germany"
},
"team": added_team.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});

View File

@@ -22,7 +22,7 @@ describe('POST /api/scans illegally', () => {
let added_track; let added_track;
let added_station; let added_station;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -109,7 +109,7 @@ describe('POST /api/scans successfully', () => {
let added_track; let added_track;
let added_station; let added_station;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -179,7 +179,7 @@ describe('POST /api/scans successfully via scan station', () => {
let added_track; let added_track;
let added_station; let added_station;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -24,7 +24,7 @@ describe('DELETE scan', () => {
let added_station; let added_station;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -38,7 +38,7 @@ describe('adding + getting scans', () => {
let added_station; let added_station;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data

View File

@@ -22,7 +22,7 @@ describe('adding + updating illegally', () => {
let added_station; let added_station;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
@@ -123,7 +123,7 @@ describe('adding + updating successfilly', () => {
let added_station2; let added_station2;
let added_scan; let added_scan;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organizations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data