mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 13:47:33 +01:00
Compare commits
706 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8ea3bd23a | ||
|
|
0ce11b82df | ||
|
|
b4c47b4afd | ||
|
|
4777850601 | ||
|
|
9a3e208c9b | ||
|
|
792d5998b0 | ||
|
|
53515fd3f4 | ||
|
|
946147a4aa | ||
|
|
983ea7c6c7 | ||
|
|
1135ab946e | ||
|
|
5a15c73fca | ||
|
|
3f99c14a37 | ||
|
|
9e515d96c3 | ||
|
|
40e0017b17 | ||
|
|
251563690e | ||
|
|
83070e211d | ||
|
|
3be075ad43 | ||
|
|
043e0fb819 | ||
|
|
9d473cc92e | ||
|
|
99dec2eb0c | ||
|
|
cbb04d221d | ||
|
|
1b93f20451 | ||
|
|
0f374abd27 | ||
|
|
a4a8ac6c5e | ||
|
|
3854c6f62f | ||
|
|
82cd53f8cb | ||
|
|
6f7cd96e9f | ||
|
|
821fc1d9c0 | ||
|
|
e4eca4b767 | ||
|
|
bd3de3c48c | ||
|
|
9f09a0396b | ||
|
|
f16e0bd044 | ||
|
|
c91de90fff | ||
|
|
380fb0abf4 | ||
|
|
43b607aedd | ||
|
|
4c832ad36c | ||
|
|
76ae41875d | ||
|
|
7a5a856ac6 | ||
|
|
0bfd709116 | ||
|
|
d7f6c3bc1b | ||
|
|
3eb164adcc | ||
|
|
7bd2cbcf04 | ||
|
|
087498760a | ||
|
|
0e26fcce98 | ||
|
|
8d0060d511 | ||
|
|
0af94b2b44 | ||
|
|
a7b5b6e20e | ||
|
|
5f93aad925 | ||
|
|
4289becccc | ||
|
|
eeddd3f366 | ||
|
|
6ce2caecf9 | ||
|
|
6b933914ef | ||
|
|
060e68ef95 | ||
|
|
a486ded6dd | ||
|
|
7884f4ce9a | ||
|
|
1c82fa012d | ||
|
|
924723bce6 | ||
|
|
b696dde6ba | ||
|
|
e8d0557cb6 | ||
|
|
cdb6acd4a0 | ||
|
|
128bd4b9cd | ||
|
|
fc5f6a31ee | ||
|
|
1f0fa500bb | ||
|
|
36276d5d3f | ||
|
|
5c2c87f523 | ||
|
|
c4f2dafc95 | ||
|
|
f09b65e108 | ||
|
|
a0f42b0e3e | ||
|
|
e10655a5b4 | ||
|
|
d519940931 | ||
|
|
58a43f51d8 | ||
|
|
d25a5fcd57 | ||
|
|
4085d7a5bb | ||
|
|
6c4e1a326f | ||
|
|
9cf8c0a824 | ||
|
|
e1f9643ffd | ||
|
|
1d5c1d5a5f | ||
|
|
df7c0a005c | ||
|
|
c60481ab34 | ||
|
|
13818b7634 | ||
|
|
b2e834c74c | ||
|
|
4a9cfe8ce5 | ||
|
|
2419b219ba | ||
|
|
0b8ce63c76 | ||
|
|
95e541ae75 | ||
|
|
85c6c19235 | ||
|
|
07e4b2c463 | ||
|
|
7b2081ab03 | ||
|
|
e749e42665 | ||
|
|
0b82722d27 | ||
|
|
f35ef3a046 | ||
|
|
5656b9c6ca | ||
|
|
1e3d7acf06 | ||
|
|
b7e391e074 | ||
|
|
b2368e7804 | ||
|
|
85880d6bb5 | ||
|
|
352b8143f3 | ||
|
|
7fe3870297 | ||
|
|
aff32b0e71 | ||
|
|
4ff56b17e7 | ||
|
|
03283d2e52 | ||
|
|
07909ac93a | ||
|
|
506b155cfa | ||
|
|
80bd41928c | ||
|
|
be3bd25f00 | ||
|
|
3e365f2b4e | ||
|
|
e1b08e3a20 | ||
|
|
01281b6414 | ||
|
|
0b65ac6c4f | ||
|
|
0d12686a10 | ||
|
|
8c4d1a67ac | ||
|
|
e58fbcc34c | ||
|
|
1a66a680dc | ||
|
|
fc08b753cd | ||
|
|
7a73f5bb83 | ||
|
|
6ce1f6f32e | ||
|
|
50278db1d6 | ||
|
|
1195560b0c | ||
|
|
33c639e28b | ||
|
|
c2b106564f | ||
|
|
fe636b9bd2 | ||
|
|
7835fe1deb | ||
|
|
8fb0d0899d | ||
|
|
abb8dc4dc1 | ||
|
|
910a76db68 | ||
|
|
2f792d51f8 | ||
|
|
6cc925b535 | ||
|
|
87d86ee632 | ||
|
|
b387d77128 | ||
|
|
e644ae83fd | ||
|
|
ae21680a5f | ||
|
|
c1767eca1b | ||
|
|
d20cd1bbf1 | ||
|
|
3e45f5af41 | ||
|
|
23cc2b9d21 | ||
|
|
58c4fcd506 | ||
|
|
2878abc130 | ||
|
|
a8cb6e3409 | ||
|
|
2caa540006 | ||
|
|
a2261e3591 | ||
|
|
90d498ff96 | ||
|
|
928327e02a | ||
|
|
f454700722 | ||
|
|
83bce24e1f | ||
|
|
e7979a99e6 | ||
|
|
5c648af2ea | ||
|
|
2ad4bee816 | ||
|
|
e0291cf432 | ||
|
|
bac9121153 | ||
|
|
d178928c45 | ||
|
|
9a6aa5f443 | ||
|
|
e277a088ee | ||
|
|
e083df64e4 | ||
|
|
dae37c17d6 | ||
|
|
1d81916674 | ||
|
|
2a225c2376 | ||
|
|
bd9d9d31c3 | ||
|
|
f1b5ce9c66 | ||
|
|
c08b25101b | ||
|
|
9fd0e27c66 | ||
|
|
994082a1d8 | ||
|
|
0e6e7adb06 | ||
|
|
8486b9631f | ||
|
|
3f04c8abf5 | ||
|
|
89e1c69728 | ||
|
|
5e935230a4 | ||
|
|
9ad50be6ca | ||
|
|
1ff3f3d4e7 | ||
|
|
0b35aefdc9 | ||
|
|
0d374d817c | ||
|
|
034058301d | ||
|
|
ae2d50c5b8 | ||
|
|
fff16a86a5 | ||
|
|
c7309ae179 | ||
|
|
ef42fba049 | ||
|
|
d75f926136 | ||
|
|
78612a91dd | ||
|
|
8bcd93075b | ||
|
|
f318afb8cf | ||
|
|
b954379f38 | ||
|
|
e5c060a80b | ||
|
|
6668aae89b | ||
|
|
9b62804a5c | ||
|
|
d21e29462c | ||
|
|
6bccd2a866 | ||
|
|
caea222330 | ||
|
|
8ecbdc1448 | ||
|
|
ee20b1eea8 | ||
|
|
ff62c6eea0 | ||
|
|
57cd4d44cd | ||
|
|
e989503cfa | ||
|
|
431cec7634 | ||
|
|
2a367ab3a7 | ||
|
|
bc91dd81e9 | ||
|
|
201085651b | ||
|
|
bb395a7ad8 | ||
|
|
264aad79ac | ||
|
|
9c797e6a54 | ||
|
|
e6c3d00665 | ||
|
|
660928323e | ||
|
|
298a79b58d | ||
|
|
77f3bb53de | ||
|
|
17d8a7b706 | ||
|
|
1d8a5b1952 | ||
|
|
f548103f4c | ||
|
|
2595ccb2b4 | ||
|
|
ceb4288b17 | ||
|
|
3ebd37f7cb | ||
|
|
ff3df55639 | ||
|
|
080c4b3e20 | ||
|
|
e939799800 | ||
|
|
b7797b3e6c | ||
|
|
55bd35d7d3 | ||
|
|
b9ae03f795 | ||
|
|
75f6398de2 | ||
|
|
4004887ddd | ||
|
|
ef4d761e0c | ||
|
|
a1fb702d1e | ||
|
|
868759d3e8 | ||
|
|
45a9d6d17b | ||
|
|
cc766d2260 | ||
|
|
e710a00e74 | ||
|
|
bad06ba449 | ||
|
|
ccb088e127 | ||
|
|
4a4d48aed8 | ||
|
|
da8006506b | ||
|
|
d451d01b18 | ||
|
|
53555a0f16 | ||
|
|
962236846a | ||
|
|
aae8f2923c | ||
|
|
61956336ea | ||
|
|
0be1f3eb7c | ||
|
|
fe04b56ecc | ||
|
|
7e772924f6 | ||
|
|
901d11c61f | ||
|
|
80b15ac5e9 | ||
|
|
78b49b9c7e | ||
|
|
8874558827 | ||
|
|
ea5ce64db6 | ||
|
|
10b69986c0 | ||
|
|
2d35009bee | ||
|
|
d267f09d04 | ||
|
|
f23dcf59ff | ||
|
|
8eb9402c0e | ||
|
|
a7f2579f6c | ||
|
|
ada09f3d5a | ||
|
|
8fdee5a669 | ||
|
|
3e4d245eba | ||
|
|
b21cd4a2b6 | ||
|
|
e956bbdf79 | ||
|
|
446154b97f | ||
|
|
18de42b13d | ||
|
|
98fd509530 | ||
|
|
d932d6d448 | ||
|
|
be4c777382 | ||
|
|
375a1f3156 | ||
|
|
ca2f2ba9ce | ||
|
|
165ca8737b | ||
|
|
f137342d88 | ||
|
|
94db493974 | ||
|
|
ee5c761680 | ||
|
|
b711c1672b | ||
|
|
d675e80555 | ||
|
|
2c1ca7629d | ||
|
|
b5d5367363 | ||
|
|
13af1fa88d | ||
|
|
b721155f01 | ||
|
|
b8aacc03e3 | ||
|
|
844d3fbf37 | ||
|
|
4d1b239231 | ||
|
|
b9aaccdf13 | ||
|
|
0155491a68 | ||
|
|
ef412c7185 | ||
|
|
c15b55808e | ||
|
|
28ddebf4a9 | ||
|
|
5f0919d1c5 | ||
|
|
0cbd6fb4d7 | ||
|
|
2eab8b2c8b | ||
|
|
b35bd18282 | ||
|
|
732a46d2db | ||
|
|
4f1d4aa73a | ||
|
|
92f2079b76 | ||
|
|
63f5773172 | ||
|
|
93290ec6d5 | ||
|
|
be6c2a002f | ||
|
|
e6bd67a53a | ||
|
|
6ab3bac96c | ||
|
|
ee97da1112 | ||
|
|
3c948beb84 | ||
|
|
f590c485dc | ||
|
|
64063544e6 | ||
|
|
0910f65fc0 | ||
|
|
fdc0e0f5fe | ||
|
|
d225a7ca54 | ||
|
|
5b7c4bf03f | ||
|
|
dddd8269b6 | ||
|
|
fd724a36ff | ||
|
|
5b329db357 | ||
|
|
c1cad5c0a9 | ||
|
|
94b5ed9dab | ||
|
|
0ac976e8c1 | ||
|
|
b1f42dcac9 | ||
|
|
ed8bd84257 | ||
|
|
4e8c08ba9b | ||
|
|
e294ed836d | ||
|
|
c86da9783b | ||
|
|
64a608e7e7 | ||
|
|
767f844cea | ||
|
|
00a686dcf6 | ||
|
|
0ca3c1f94d | ||
|
|
2f699e24d7 | ||
|
|
faa0611ab2 | ||
|
|
08c8f26b80 | ||
|
|
8904c58510 | ||
|
|
d10f1304de | ||
|
|
e28992060c | ||
|
|
df860c9401 | ||
|
|
87923b7f0d | ||
|
|
b2d6a9474d | ||
|
|
5fac4a943c | ||
|
|
5d0be7bc72 | ||
|
|
9e6394c38c | ||
|
|
cc97935ffd | ||
|
|
6ea4d96830 | ||
|
|
a63ba51497 | ||
|
|
04a7fd25a6 | ||
|
|
7cb045781b | ||
|
|
f8d799d55c | ||
|
|
5bd9fcc99d | ||
|
|
84cafc4081 | ||
|
|
d77a17112c | ||
|
|
4f9d97d38f | ||
|
|
40060e8ff5 | ||
|
|
508d97d374 | ||
|
|
fd125352b7 | ||
|
|
f8bd1be4a3 | ||
|
|
ec37524164 | ||
|
|
c66d2cb469 | ||
|
|
87b9e72b56 | ||
|
|
962662fe7c | ||
|
|
f63d2e47f0 | ||
|
|
349a1032b6 | ||
|
|
476131835d | ||
|
|
8237b7f2de | ||
|
|
6ee2b3690a | ||
|
|
a08cca807a | ||
|
|
8c51f36784 | ||
|
|
d35f81cdae | ||
|
|
1d1b25391f | ||
|
|
ee09c76c08 | ||
|
|
c478748436 | ||
|
|
61606cb69d | ||
|
|
ec81c02d72 | ||
|
|
166da3c2f8 | ||
|
|
23b72a673d | ||
|
|
d22b4bb2f7 | ||
|
|
aaebd4da77 | ||
|
|
b128e7874e | ||
|
|
1e10e20a24 | ||
|
|
b1aeb8ed87 | ||
|
|
2cb80e2275 | ||
|
|
ee32e24ff2 | ||
|
|
af40c437be | ||
|
|
a99150c485 | ||
|
|
696b67204d | ||
|
|
4f3536e887 | ||
|
|
07e5bf1437 | ||
|
|
d2ca738256 | ||
|
|
f7983f39eb | ||
|
|
7c954f7073 | ||
|
|
82d0e737a6 | ||
|
|
f8213aaf1b | ||
|
|
2335ad4167 | ||
|
|
d84631255b | ||
|
|
0b352b9103 | ||
|
|
19b75c6257 | ||
|
|
b66904a3a7 | ||
|
|
cfbfec34aa | ||
|
|
88f28188a1 | ||
|
|
fce5be2e8f | ||
|
|
1d68cbfaa2 | ||
|
|
a44222a350 | ||
|
|
4d2510e322 | ||
|
|
3b5ed33e03 | ||
|
|
0a6bf92b6b | ||
|
|
05ae40bc2e | ||
|
|
57e96ea092 | ||
|
|
ea49b5b8e0 | ||
|
|
11a5de714a | ||
|
|
f74b4d3e73 | ||
|
|
ab6fdb99af | ||
|
|
e3efa557dd | ||
|
|
a6cea47789 | ||
|
|
5a200a88bd | ||
|
|
545499ea0b | ||
|
|
3e7f4229ec | ||
|
|
56d5f77b6e | ||
|
|
efdf5a2e16 | ||
|
|
add3a2887f | ||
|
|
0ed7c7596a | ||
|
|
55a452694f | ||
|
|
cd4d5f83ff | ||
|
|
8220199e49 | ||
|
|
bd1f6918ba | ||
|
|
3d99a64e96 | ||
|
|
76f9204417 | ||
|
|
5b21e62647 | ||
|
|
5e76d6df21 | ||
|
|
fad59b9a8d | ||
|
|
f218a432ec | ||
|
|
7348145b7d | ||
|
|
ba2832d21f | ||
|
|
688f5084a1 | ||
|
|
d5955b8889 | ||
|
|
01fd17ee3f | ||
|
|
979497dd35 | ||
|
|
1d3db244ba | ||
|
|
80ca074352 | ||
|
|
6d4f9e0759 | ||
|
|
d096695559 | ||
|
|
a2c8b8b05c | ||
|
|
8750701c08 | ||
|
|
900676bf0a | ||
|
|
e219daf44c | ||
|
|
1b12a6b51f | ||
|
|
8441b0a3d6 | ||
|
|
0667695390 | ||
|
|
4d322c1bf6 | ||
|
|
a855ddacc7 | ||
|
|
9d48ef7322 | ||
|
|
73ecdced01 | ||
|
|
1c17b415f0 | ||
|
|
2991f7acfb | ||
|
|
9dbfb565bb | ||
|
|
f42e22b58f | ||
|
|
95f3315796 | ||
|
|
18ab57eb91 | ||
|
|
0dcbd8ccb8 | ||
|
|
ed82b46f7b | ||
|
|
dcc3044685 | ||
|
|
5cd62d7052 | ||
|
|
5e232d8c9f | ||
|
|
13793f8b3c | ||
|
|
55f875f95a | ||
|
|
14576be374 | ||
|
|
4cb2c26475 | ||
|
|
b66a0b76ef | ||
|
|
dd313b17b5 | ||
|
|
bb01475e02 | ||
|
|
757959529b | ||
|
|
71ad1957b1 | ||
|
|
3ba5ea1d2d | ||
|
|
902da35f2b | ||
|
|
aaa16a9527 | ||
|
|
b98e95ee45 | ||
|
|
757160d6b7 | ||
|
|
4cf68eb018 | ||
|
|
e91d5e5664 | ||
|
|
b9e12aca3e | ||
|
|
53ca9475ee | ||
|
|
e212842b50 | ||
|
|
d2f7cba43d | ||
|
|
84558f79d6 | ||
|
|
178e59f287 | ||
|
|
7acccc0763 | ||
|
|
8ac21d2fd4 | ||
|
|
7873800f87 | ||
|
|
727041f020 | ||
|
|
de0c62a37f | ||
|
|
68f420991e | ||
|
|
f211ebeb0a | ||
|
|
b91ef9f539 | ||
|
|
ac0601630e | ||
|
|
3239491144 | ||
|
|
b912a83f22 | ||
|
|
fb3a9740bd | ||
|
|
817c943860 | ||
|
|
0aba448c48 | ||
|
|
c3b0a73507 | ||
|
|
b218eb2c00 | ||
|
|
37d9f76fea | ||
|
|
7f2e12ba23 | ||
|
|
21b43287e3 | ||
|
|
357b48dc8f | ||
|
|
2cbd78b139 | ||
|
|
ee5dd5842b | ||
|
|
074b8138de | ||
|
|
cd0b9c0a96 | ||
|
|
a09516944d | ||
|
|
b82660823d | ||
|
|
fde4402fbb | ||
|
|
5fe0776074 | ||
|
|
d218f316d3 | ||
|
|
f19e69948a | ||
|
|
e6807d36b5 | ||
|
|
1ece230621 | ||
|
|
d934d9d759 | ||
|
|
bf7fabb20a | ||
|
|
88a2f317d8 | ||
|
|
a30c4379a6 | ||
|
|
b509c6631d | ||
|
|
5a725fa4b0 | ||
|
|
6b5173ecbf | ||
|
|
53d8d2fc6a | ||
|
|
dbe2143b7a | ||
|
|
7b687280d7 | ||
|
|
8db6c8bd4f | ||
|
|
bf91dacb94 | ||
|
|
33e0892e95 | ||
|
|
42b146d5d0 | ||
|
|
2bebaf2cf8 | ||
|
|
6181328ac1 | ||
|
|
c64d4b0914 | ||
|
|
f94fd0d69d | ||
|
|
2cd66436bc | ||
|
|
81a17738b8 | ||
|
|
b6b953ec46 | ||
|
|
ab34c83a9d | ||
|
|
9cea86f4e0 | ||
|
|
1b7a705bf9 | ||
|
|
e2c5b9058b | ||
|
|
cc751960ac | ||
|
|
433c73c9d3 | ||
|
|
680c2162a7 | ||
|
|
a2b38ffb02 | ||
|
|
6395870c00 | ||
|
|
9562ba432f | ||
|
|
8a3a83de37 | ||
|
|
745edd731d | ||
|
|
53b195931c | ||
|
|
37ae467fff | ||
|
|
52a7112591 | ||
|
|
d7d7d64b45 | ||
|
|
fd13771088 | ||
|
|
c9d725ec20 | ||
|
|
3203bffeaa | ||
|
|
3f47cdd9a2 | ||
|
|
8b15d94ae1 | ||
|
|
e76bdbd62d | ||
|
|
067e869141 | ||
|
|
51224a69d9 | ||
|
|
f56018d46a | ||
|
|
b846185f8a | ||
|
|
ff81e55839 | ||
|
|
9a3cdb5deb | ||
|
|
47ad7305f5 | ||
|
|
d9b5bbe2a9 | ||
|
|
c2fe04367f | ||
|
|
abcc77b7d6 | ||
|
|
07cbf45265 | ||
|
|
c035435476 | ||
|
|
89fdd8a8bb | ||
|
|
d406da4081 | ||
|
|
d74786ef85 | ||
|
|
64a3d08ce3 | ||
|
|
f635f178da | ||
|
|
1a7461a8a2 | ||
|
|
cc13c4f28e | ||
|
|
239f78674b | ||
|
|
d691dee2ca | ||
|
|
481bd6727d | ||
|
|
d0fc1e0751 | ||
|
|
b07dbb7752 | ||
|
|
34e7690c38 | ||
|
|
eca7382545 | ||
|
|
be95cd967a | ||
|
|
ce03f837c7 | ||
|
|
808885425f | ||
|
|
39a35f44ef | ||
|
|
2b2e1d4b9a | ||
|
|
869411c0e9 | ||
|
|
7484ecf729 | ||
|
|
8f2435c37c | ||
|
|
3265440bc4 | ||
|
|
acf514e9cb | ||
|
|
2789d44dbf | ||
|
|
b579f31e9e | ||
|
|
5e781017ab | ||
|
|
b48f850eac | ||
|
|
5d6b6ed29a | ||
|
|
7fbc68511b | ||
|
|
ee2858199b | ||
|
|
b1dd79f75c | ||
|
|
1ac4dd8171 | ||
|
|
4f86abd6b2 | ||
|
|
23b0688abb | ||
|
|
38efe83cc7 | ||
|
|
302bc899d7 | ||
|
|
8048cf9a97 | ||
|
|
20548daccf | ||
|
|
2dadd74097 | ||
|
|
9f494360ef | ||
|
|
b7f3c0f389 | ||
|
|
7195ac15b9 | ||
|
|
a5ef6a129e | ||
|
|
38f5d63d29 | ||
|
|
43194b71ce | ||
|
|
e4a347a3cb | ||
|
|
7eaf3e04ab | ||
|
|
b6b03751c4 | ||
|
|
818d5e4eb6 | ||
|
|
f871c7cf63 | ||
|
|
e9eddec0c4 | ||
|
|
a48a6a292d | ||
|
|
12aef475c8 | ||
|
|
112e4e1d76 | ||
|
|
90eebbcd70 | ||
|
|
86ae5f3e44 | ||
|
|
3922415314 | ||
|
|
6c71abfac8 | ||
|
|
6ab08a7d52 | ||
|
|
dc46127fc7 | ||
|
|
b54f031acd | ||
|
|
eafa2f8cdd | ||
|
|
1815d2b6d3 | ||
|
|
14cba76ba8 | ||
|
|
fe45940d46 | ||
|
|
7dac53867b | ||
|
|
6f64cb7d9b | ||
|
|
06812878b5 | ||
|
|
8714c7d162 | ||
|
|
e66f4e7812 | ||
|
|
c73f565f65 | ||
|
|
82e21df943 | ||
|
|
18ed148320 | ||
|
|
dadb752087 | ||
|
|
37b29d3449 | ||
|
|
bb2ed249b9 | ||
|
|
bb90dde1b6 | ||
|
|
5299c8d406 | ||
|
|
8b81e38538 | ||
|
|
8e05a1b489 | ||
|
|
aafcbe60a3 | ||
|
|
56d1b77215 | ||
|
|
61da558a5d | ||
|
|
95b283676a | ||
|
|
6e7e81206a | ||
|
|
af74cc7c64 | ||
|
|
a9e2a17077 | ||
|
|
92057dbe17 | ||
|
|
b4ab525be5 | ||
|
|
d3c464d5ea | ||
|
|
804fe1c6d5 | ||
|
|
3d757c7814 | ||
|
|
3c5025a78e | ||
|
|
cd9630332d | ||
|
|
ed21a37e5a | ||
|
|
16256ee190 | ||
|
|
fdecc8ce16 | ||
|
|
3cc49f6637 | ||
|
|
47f49f4256 | ||
|
|
4f4bb52360 | ||
|
|
3748b3046b | ||
|
|
5cd0f56811 | ||
|
|
456c5e57bc | ||
|
|
185b20995a | ||
|
|
fdf2e590ea | ||
|
|
994123c387 | ||
|
|
273590716c | ||
|
|
6818a094ee | ||
|
|
c99855cef4 | ||
|
|
6845943ed0 | ||
|
|
044fe17757 | ||
|
|
ad0ede8d01 | ||
|
|
23815e89e1 | ||
|
|
cfd19ac694 | ||
|
|
0897ab5dc9 | ||
|
|
5c6e8a7331 | ||
|
|
c576c5261e | ||
|
|
2c250bfcd9 | ||
|
|
bbd98517ff | ||
|
|
392b54aa7b | ||
|
|
60b26d4ec0 | ||
|
|
fa1fef11d6 | ||
|
|
75e3f15352 | ||
|
|
5670be26c7 | ||
|
|
9fc03cb91a | ||
|
|
7e80406181 | ||
|
|
60a6f6f2f6 | ||
|
|
92d68e5c6e | ||
|
|
1c51e62e43 | ||
|
|
f049d29d1b | ||
|
|
6e7d8d93fe | ||
|
|
bc861133e1 | ||
|
|
31ef21f25c | ||
|
|
fd700f92ae | ||
|
|
f41665f5a9 | ||
|
|
8b385c0b7b | ||
|
|
282f8db933 | ||
|
|
662b08c242 | ||
|
|
97e1465899 | ||
|
|
7cb0f5145d | ||
|
|
5b6217a0bf | ||
|
|
09e4c88606 | ||
|
|
13bae96708 | ||
|
|
6241001eef | ||
|
|
dc5722d0de | ||
|
|
e3b2443029 | ||
|
|
ca5927fe73 | ||
|
|
5a0eed7eae | ||
|
|
532881e679 | ||
|
|
27d763a46c | ||
|
|
b7e601be16 | ||
|
|
395676fcb1 | ||
|
|
cc4df1c995 | ||
|
|
48eada2c37 |
4
.github/CONTRIBUTING.md
vendored
4
.github/CONTRIBUTING.md
vendored
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
# Pull Request
|
# Pull Request
|
||||||
|
|
||||||
[Please see these instructions for adding a pull request](http://habitica.wikia.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API)
|
[Please see these instructions for adding a pull request](http://habitica.fandom.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API)
|
||||||
|
|
||||||
# Requesting a feature
|
# Requesting a feature
|
||||||
|
|
||||||
@@ -12,4 +12,4 @@ Habitica uses [Trello](https://trello.com/b/EpoYEYod/habitica) to track feature
|
|||||||
|
|
||||||
# Contributing Code
|
# Contributing Code
|
||||||
|
|
||||||
See [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica#Coders_.28Web_.26_Mobile.29)
|
See [Contributing to Habitica](http://habitica.fandom.com/wiki/Contributing_to_Habitica#Coders_.28Web_.26_Mobile.29)
|
||||||
|
|||||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
[//]: # (Note: See http://habitica.wikia.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API for more info)
|
[//]: # (Note: See http://habitica.fandom.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API for more info)
|
||||||
|
|
||||||
[//]: # (Put Issue # here, if applicable. This will automatically close the issue if your PR is merged in)
|
[//]: # (Put Issue # here, if applicable. This will automatically close the issue if your PR is merged in)
|
||||||
Fixes put_#_and_issue_numer_here
|
Fixes put_#_and_issue_numer_here
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -40,6 +40,7 @@ test/client/unit/coverage
|
|||||||
test/client/e2e/reports
|
test/client/e2e/reports
|
||||||
test/client-old/spec/mocks/translations.js
|
test/client-old/spec/mocks/translations.js
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
# Elastic Beanstalk Files
|
# Elastic Beanstalk Files
|
||||||
.elasticbeanstalk/*
|
.elasticbeanstalk/*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '8'
|
- '10'
|
||||||
services:
|
services:
|
||||||
- mongodb
|
- mongodb
|
||||||
cache:
|
cache:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:8
|
FROM node:10
|
||||||
|
|
||||||
ENV ADMIN_EMAIL admin@habitica.com
|
ENV ADMIN_EMAIL admin@habitica.com
|
||||||
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
|
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
|
||||||
@@ -8,6 +8,7 @@ ENV BASE_URL https://habitica.com
|
|||||||
ENV FACEBOOK_KEY 128307497299777
|
ENV FACEBOOK_KEY 128307497299777
|
||||||
ENV GA_ID UA-33510635-1
|
ENV GA_ID UA-33510635-1
|
||||||
ENV GOOGLE_CLIENT_ID 1035232791481-32vtplgnjnd1aufv3mcu1lthf31795fq.apps.googleusercontent.com
|
ENV GOOGLE_CLIENT_ID 1035232791481-32vtplgnjnd1aufv3mcu1lthf31795fq.apps.googleusercontent.com
|
||||||
|
ENV LOGGLY_CLIENT_TOKEN ab5663bf-241f-4d14-8783-7d80db77089a
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV production
|
||||||
ENV STRIPE_PUB_KEY pk_85fQ0yMECHNfHTSsZoxZXlPSwSNfA
|
ENV STRIPE_PUB_KEY pk_85fQ0yMECHNfHTSsZoxZXlPSwSNfA
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:8
|
FROM node:10
|
||||||
|
|
||||||
# Install global packages
|
# Install global packages
|
||||||
RUN npm install -g gulp-cli mocha
|
RUN npm install -g gulp-cli mocha
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ Habitica [.
|
For an introduction to the technologies used and how the software is organized, refer to [Guidance for Blacksmiths](http://habitica.fandom.com/wiki/Guidance_for_Blacksmiths).
|
||||||
|
|
||||||
To set up a local install of Habitica for development and testing on various platforms, see [Setting up Habitica Locally](http://habitica.wikia.com/wiki/Setting_up_Habitica_Locally).
|
To set up a local install of Habitica for development and testing on various platforms, see [Setting up Habitica Locally](http://habitica.fandom.com/wiki/Setting_up_Habitica_Locally).
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ minimal dependencies on the developer's local platform. It can be used
|
|||||||
on a variety of systems including Windows, Mac OS X, and Linux.
|
on a variety of systems including Windows, Mac OS X, and Linux.
|
||||||
|
|
||||||
Instructions for using the Habitica Vagrant environment are in
|
Instructions for using the Habitica Vagrant environment are in
|
||||||
[Setting up Habitica Locally](http://habitica.wikia.com/wiki/Setting_up_Habitica_Locally).
|
[Setting up Habitica Locally](http://habitica.fandom.com/wiki/Setting_up_Habitica_Locally).
|
||||||
|
|||||||
@@ -1,115 +1,83 @@
|
|||||||
{
|
{
|
||||||
"PORT":3000,
|
"ADMIN_EMAIL": "you@example.com",
|
||||||
"ENABLE_CONSOLE_LOGS_IN_PROD":"false",
|
"AMAZON_PAYMENTS_CLIENT_ID": "CLIENT_ID",
|
||||||
"IP":"0.0.0.0",
|
"AMAZON_PAYMENTS_MODE": "sandbox",
|
||||||
"WEB_CONCURRENCY":1,
|
"AMAZON_PAYMENTS_MWS_KEY": "MWS_KEY",
|
||||||
"BASE_URL":"http://localhost:3000",
|
"AMAZON_PAYMENTS_MWS_SECRET": "MWS_SECRET",
|
||||||
"FACEBOOK_KEY":"123456789012345",
|
"AMAZON_PAYMENTS_SELLER_ID": "SELLER_ID",
|
||||||
"FACEBOOK_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
"AMPLITUDE_KEY": "AMPLITUDE_KEY",
|
||||||
"GOOGLE_CLIENT_ID":"123456789012345",
|
"AMPLITUDE_SECRET": "AMPLITUDE_SECRET",
|
||||||
"GOOGLE_CLIENT_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
"BASE_URL": "http://localhost:3000",
|
||||||
"PLAY_API": {
|
"CRON_SAFE_MODE": "false",
|
||||||
"CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
"CRON_SEMI_SAFE_MODE": "false",
|
||||||
"CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
"DISABLE_REQUEST_LOGGING": "true",
|
||||||
"ACCESS_TOKEN":"aaaabbbbccccddddeeeeffff00001111",
|
"EMAILS_COMMUNITY_MANAGER_EMAIL": "admin@habitica.com",
|
||||||
"REFRESH_TOKEN":"aaaabbbbccccddddeeeeffff00001111"
|
"EMAILS_PRESS_ENQUIRY_EMAIL": "admin@habitica.com",
|
||||||
},
|
"EMAILS_TECH_ASSISTANCE_EMAIL": "admin@habitica.com",
|
||||||
"NODE_DB_URI":"mongodb://localhost/habitrpg",
|
"EMAIL_SERVER_AUTH_PASSWORD": "password",
|
||||||
"TEST_DB_URI":"mongodb://localhost/habitrpg_test",
|
"EMAIL_SERVER_AUTH_USER": "user",
|
||||||
"NODE_ENV":"development",
|
"EMAIL_SERVER_URL": "http://example.com",
|
||||||
"ENABLE_CONSOLE_LOGS_IN_TEST": "false",
|
"ENABLE_CONSOLE_LOGS_IN_PROD": "false",
|
||||||
"CRON_SAFE_MODE":"false",
|
"ENABLE_CONSOLE_LOGS_IN_TEST": "false",
|
||||||
"CRON_SEMI_SAFE_MODE":"false",
|
"FACEBOOK_KEY": "123456789012345",
|
||||||
"MAINTENANCE_MODE": "false",
|
"FACEBOOK_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"SESSION_SECRET":"YOUR SECRET HERE",
|
"FLAG_REPORT_EMAIL": "email@example.com, email2@example.com",
|
||||||
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
"GA_ID": "GA_ID",
|
||||||
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
"GOOGLE_CLIENT_ID": "123456789012345",
|
||||||
"ADMIN_EMAIL": "you@example.com",
|
"GOOGLE_CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"SMTP_USER":"user@example.com",
|
"IAP_GOOGLE_KEYDIR": "/path/to/google/public/key/dir/",
|
||||||
"SMTP_PASS":"password",
|
"IGNORE_REDIRECT": "true",
|
||||||
"SMTP_SERVICE":"Gmail",
|
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"SMTP_HOST":"example.com",
|
"LOGGLY_CLIENT_TOKEN": "token",
|
||||||
"SMTP_PORT": 587,
|
"LOGGLY_SUBDOMAIN": "example-subdomain",
|
||||||
"SMTP_TLS": true,
|
"LOGGLY_TOKEN": "example-token",
|
||||||
"STRIPE_API_KEY":"aaaabbbbccccddddeeeeffff00001111",
|
"MAINTENANCE_MODE": "false",
|
||||||
"STRIPE_PUB_KEY":"22223333444455556666777788889999",
|
"NODE_DB_URI": "mongodb://localhost/habitrpg",
|
||||||
"NEW_RELIC_LICENSE_KEY":"NEW_RELIC_LICENSE_KEY",
|
"NODE_ENV": "development",
|
||||||
"NEW_RELIC_NO_CONFIG_FILE":"true",
|
"PATH": "bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin",
|
||||||
"NEW_RELIC_APPLICATION_ID":"NEW_RELIC_APPLICATION_ID",
|
"PAYPAL_BILLING_PLANS_basic_12mo": "basic_12mo",
|
||||||
"NEW_RELIC_API_KEY":"NEW_RELIC_API_KEY",
|
"PAYPAL_BILLING_PLANS_basic_3mo": "basic_3mo",
|
||||||
"GA_ID": "GA_ID",
|
"PAYPAL_BILLING_PLANS_basic_6mo": "basic_6mo",
|
||||||
"AMPLITUDE_KEY": "AMPLITUDE_KEY",
|
"PAYPAL_BILLING_PLANS_basic_earned": "basic_earned",
|
||||||
"AMPLITUDE_SECRET": "AMPLITUDE_SECRET",
|
"PAYPAL_BILLING_PLANS_google_6mo": "google_6mo",
|
||||||
"AMAZON_PAYMENTS": {
|
"PAYPAL_CLIENT_ID": "client_id",
|
||||||
"SELLER_ID": "SELLER_ID",
|
"PAYPAL_CLIENT_SECRET": "client_secret",
|
||||||
"CLIENT_ID": "CLIENT_ID",
|
"PAYPAL_EXPERIENCE_PROFILE_ID": "xp_profile_id",
|
||||||
"MWS_KEY": "",
|
"PAYPAL_MODE": "sandbox",
|
||||||
"MWS_SECRET": ""
|
"PLAY_API_ACCESS_TOKEN": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
},
|
"PLAY_API_CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"FLAG_REPORT_EMAIL": "email@mod.com,email2@mod.com",
|
"PLAY_API_CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"EMAIL_SERVER": {
|
"PLAY_API_REFRESH_TOKEN": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"url": "http://example.com",
|
"PORT": 3000,
|
||||||
"authUser": "user",
|
"PUSH_CONFIGS_APN_ENABLED": "false",
|
||||||
"authPassword": "password"
|
"PUSH_CONFIGS_APN_KEY": "xxxxxxxxxx",
|
||||||
},
|
"PUSH_CONFIGS_APN_KEY_ID": "xxxxxxxxxx",
|
||||||
"S3":{
|
"PUSH_CONFIGS_APN_TEAM_ID": "aaabbbcccd",
|
||||||
"bucket":"bucket",
|
"PUSH_CONFIGS_FCM_SERVER_API_KEY": "aaabbbcccd",
|
||||||
"accessKeyId":"accessKeyId",
|
"S3_ACCESS_KEY_ID": "accessKeyId",
|
||||||
"secretAccessKey":"secretAccessKey"
|
"S3_BUCKET": "bucket",
|
||||||
},
|
"S3_SECRET_ACCESS_KEY": "secretAccessKey",
|
||||||
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
"SESSION_SECRET": "YOUR SECRET HERE",
|
||||||
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
||||||
"PAYPAL":{
|
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
||||||
"billing_plans": {
|
"SITE_HTTP_AUTH_ENABLED": "false",
|
||||||
"basic_earned":"basic_earned",
|
"SITE_HTTP_AUTH_PASSWORD": "password",
|
||||||
"basic_3mo":"basic_3mo",
|
"SITE_HTTP_AUTH_USERNAME": "admin",
|
||||||
"basic_6mo":"basic_6mo",
|
"SLACK_FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||||
"google_6mo":"google_6mo",
|
"SLACK_FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||||
"basic_12mo":"basic_12mo"
|
"SLACK_SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id",
|
||||||
},
|
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
||||||
"mode":"sandbox",
|
"SMTP_HOST": "example.com",
|
||||||
"client_id":"client_id",
|
"SMTP_PASS": "password",
|
||||||
"client_secret":"client_secret",
|
"SMTP_PORT": 587,
|
||||||
"experience_profile_id": ""
|
"SMTP_SERVICE": "Gmail",
|
||||||
},
|
"SMTP_TLS": "true",
|
||||||
"IAP_GOOGLE_KEYDIR": "/path/to/google/public/key/dir/",
|
"SMTP_USER": "user@example.com",
|
||||||
"LOGGLY_TOKEN": "token",
|
"STRIPE_API_KEY": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
"LOGGLY_CLIENT_TOKEN": "token",
|
"STRIPE_PUB_KEY": "22223333444455556666777788889999",
|
||||||
"LOGGLY_ACCOUNT": "account",
|
"TEST_DB_URI": "mongodb://localhost/habitrpg_test",
|
||||||
"PUSH_CONFIGS": {
|
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
||||||
"GCM_SERVER_API_KEY": "",
|
"WEB_CONCURRENCY": 1,
|
||||||
"APN_ENABLED": "false",
|
"SKIP_SSL_CHECK_KEY": "key",
|
||||||
"APN_KEY_ID": "xxxxxxxxxx",
|
"ENABLE_STACKDRIVER_TRACING": "false"
|
||||||
"APN_KEY": "xxxxxxxxxx",
|
|
||||||
"APN_TEAM_ID": "aaabbbcccd",
|
|
||||||
"FCM_SERVER_API_KEY": ""
|
|
||||||
},
|
|
||||||
"SITE_HTTP_AUTH": {
|
|
||||||
"ENABLED": "false",
|
|
||||||
"USERNAME": "admin",
|
|
||||||
"PASSWORD": "password"
|
|
||||||
},
|
|
||||||
"SLACK": {
|
|
||||||
"FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
|
||||||
"FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
|
||||||
"SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id"
|
|
||||||
},
|
|
||||||
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
|
||||||
"EMAILS" : {
|
|
||||||
"COMMUNITY_MANAGER_EMAIL" : "admin@habitica.com",
|
|
||||||
"TECH_ASSISTANCE_EMAIL" : "admin@habitica.com",
|
|
||||||
"PRESS_ENQUIRY_EMAIL" : "admin@habitica.com"
|
|
||||||
},
|
|
||||||
"LOGGLY" : {
|
|
||||||
"TOKEN" : "example-token",
|
|
||||||
"SUBDOMAIN" : "exmaple-subdomain"
|
|
||||||
},
|
|
||||||
"KAFKA": {
|
|
||||||
"GROUP_ID": "",
|
|
||||||
"CLOUDKARAFKA_BROKERS": "",
|
|
||||||
"CLOUDKARAFKA_USERNAME": "",
|
|
||||||
"CLOUDKARAFKA_PASSWORD": "",
|
|
||||||
"CLOUDKARAFKA_TOPIC_PREFIX": ""
|
|
||||||
},
|
|
||||||
"MIGRATION_CONNECT_STRING": "mongodb://localhost:27017/habitrpg?auto_reconnect=true"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', (cb) => {
|
|||||||
|
|
||||||
gulp.task('test:api:unit', (done) => {
|
gulp.task('test:api:unit', (done) => {
|
||||||
let runner = exec(
|
let runner = exec(
|
||||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -180,12 +180,12 @@ gulp.task('test:api:unit', (done) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:api:unit:watch', () => {
|
gulp.task('test:api:unit:watch', () => {
|
||||||
return gulp.watch(['website/server/libs/*', 'test/api/v3/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done()));
|
return gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done()));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:api-v3:integration', (done) => {
|
gulp.task('test:api-v3:integration', (done) => {
|
||||||
let runner = exec(
|
let runner = exec(
|
||||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||||
{maxBuffer: 500 * 1024},
|
{maxBuffer: 500 * 1024},
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -217,7 +217,7 @@ gulp.task('test:api-v3:integration:separate-server', (done) => {
|
|||||||
|
|
||||||
gulp.task('test:api-v4:integration', (done) => {
|
gulp.task('test:api-v4:integration', (done) => {
|
||||||
let runner = exec(
|
let runner = exec(
|
||||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
|
testBin('istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
|
||||||
{maxBuffer: 500 * 1024},
|
{maxBuffer: 500 * 1024},
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -254,4 +254,4 @@ gulp.task('test:api-v3', gulp.series(
|
|||||||
'test:api:unit',
|
'test:api:unit',
|
||||||
'test:api-v3:integration',
|
'test:api-v3:integration',
|
||||||
done => done()
|
done => done()
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const Timer = require('./utils/timer');
|
|||||||
const connectToDb = require('./utils/connect').connectToDb;
|
const connectToDb = require('./utils/connect').connectToDb;
|
||||||
const closeDb = require('./utils/connect').closeDb;
|
const closeDb = require('./utils/connect').closeDb;
|
||||||
|
|
||||||
const message = '`This party\'s collection quest has been made easier! For details, refer to http://habitica.wikia.com/wiki/User_blog:LadyAlys/Collection_Quests_are_Now_Easier`';
|
const message = '`This party\'s collection quest has been made easier! For details, refer to http://habitica.fandom.com/wiki/User_blog:LadyAlys/Collection_Quests_are_Now_Easier`';
|
||||||
|
|
||||||
const timer = new Timer();
|
const timer = new Timer();
|
||||||
|
|
||||||
|
|||||||
66
migrations/archive/2018/20181023_veteran_pet_ladder.js
Normal file
66
migrations/archive/2018/20181023_veteran_pet_ladder.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20181023_veteran_pet_ladder';
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const set = {};
|
||||||
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
|
if (user.items.pets['Bear-Veteran']) {
|
||||||
|
set['items.pets.Fox-Veteran'] = 5;
|
||||||
|
} else if (user.items.pets['Lion-Veteran']) {
|
||||||
|
set['items.pets.Bear-Veteran'] = 5;
|
||||||
|
} else if (user.items.pets['Tiger-Veteran']) {
|
||||||
|
set['items.pets.Lion-Veteran'] = 5;
|
||||||
|
} else if (user.items.pets['Wolf-Veteran']) {
|
||||||
|
set['items.pets.Tiger-Veteran'] = 5;
|
||||||
|
} else {
|
||||||
|
set['items.pets.Wolf-Veteran'] = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
'flags.verifiedUsername': true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
migration: 1,
|
||||||
|
flags: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
109
migrations/archive/2018/20181108_username_email.js
Normal file
109
migrations/archive/2018/20181108_username_email.js
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
const MIGRATION_NAME = '20181108_username_email.js';
|
||||||
|
const AUTHOR_NAME = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
const AUTHOR_UUID = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send emails to eligible users announcing upcoming username changes
|
||||||
|
*/
|
||||||
|
|
||||||
|
import monk from 'monk';
|
||||||
|
import nconf from 'nconf';
|
||||||
|
import { sendTxn } from '../../../website/server/libs/email';
|
||||||
|
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||||
|
const BASE_URL = nconf.get('BASE_URL');
|
||||||
|
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||||
|
|
||||||
|
function processUsers (lastId) {
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
'flags.verifiedUsername': {$ne: true},
|
||||||
|
'auth.timestamps.loggedin': {$gt: new Date('2018-10-25')},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.find(query, {
|
||||||
|
sort: {_id: 1},
|
||||||
|
limit: 100,
|
||||||
|
fields: [
|
||||||
|
'_id',
|
||||||
|
'auth',
|
||||||
|
'preferences',
|
||||||
|
'profile',
|
||||||
|
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, `ERROR! ${ err}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
function updateUsers (users) {
|
||||||
|
if (!users || users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
displayData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let userPromises = users.map(updateUser);
|
||||||
|
let lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(() => delay(7000))
|
||||||
|
.then(() => {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
dbUsers.update({_id: user._id}, {$set: {migration: MIGRATION_NAME}});
|
||||||
|
|
||||||
|
sendTxn(
|
||||||
|
user,
|
||||||
|
'username-change-follow-up',
|
||||||
|
[{name: 'LOGIN_NAME', content: user.auth.local.username},
|
||||||
|
{name: 'BASE_URL', content: BASE_URL}]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
if (user._id === AUTHOR_UUID) console.warn(`${AUTHOR_NAME} processed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayData () {
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function delay (t, v) {
|
||||||
|
return new Promise(function batchPause (resolve) {
|
||||||
|
setTimeout(resolve.bind(null, v), t);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function exiting (code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) {
|
||||||
|
msg = 'ERROR!';
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
if (code) {
|
||||||
|
console.error(msg);
|
||||||
|
} else {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
109
migrations/archive/2018/20181122_turkey_day.js
Normal file
109
migrations/archive/2018/20181122_turkey_day.js
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20181122_turkey_day';
|
||||||
|
import mongoose from 'mongoose';
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const set = {};
|
||||||
|
let push;
|
||||||
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.armor_special_turkeyArmorBase !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_turkeyHelmGilded'] = false;
|
||||||
|
set['items.gear.owned.armor_special_turkeyArmorGilded'] = false;
|
||||||
|
set['items.gear.owned.back_special_turkeyTailGilded'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_turkeyHelmGilded',
|
||||||
|
_id: new mongoose.Types.ObjectId(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.armor_special_turkeyArmorGilded',
|
||||||
|
_id: new mongoose.Types.ObjectId(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.back_special_turkeyTailGilded',
|
||||||
|
_id: new mongoose.Types.ObjectId(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Gilded']) {
|
||||||
|
set['items.gear.owned.head_special_turkeyHelmBase'] = false;
|
||||||
|
set['items.gear.owned.armor_special_turkeyArmorBase'] = false;
|
||||||
|
set['items.gear.owned.back_special_turkeyTailBase'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_turkeyHelmBase',
|
||||||
|
_id: new mongoose.Types.ObjectId(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.armor_special_turkeyArmorBase',
|
||||||
|
_id: new mongoose.Types.ObjectId(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.back_special_turkeyTailBase',
|
||||||
|
_id: new mongoose.Types.ObjectId(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (user.items && user.items.pets && user.items.pets['Turkey-Gilded']) {
|
||||||
|
set['items.mounts.Turkey-Gilded'] = true;
|
||||||
|
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Base']) {
|
||||||
|
set['items.pets.Turkey-Gilded'] = 5;
|
||||||
|
} else if (user.items && user.items.pets && user.items.pets['Turkey-Base']) {
|
||||||
|
set['items.mounts.Turkey-Base'] = true;
|
||||||
|
} else {
|
||||||
|
set['items.pets.Turkey-Base'] = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
if (push) {
|
||||||
|
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||||
|
} else {
|
||||||
|
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
110
migrations/archive/2018/20181231_nye.js
Normal file
110
migrations/archive/2018/20181231_nye.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20181231_nye';
|
||||||
|
import { model as User } from '../../../website/server/models/user';
|
||||||
|
import mongoose from 'mongoose';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const set = {'flags.newStuff': true};
|
||||||
|
let push;
|
||||||
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.head_special_nye2017 !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_nye2018'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_nye2018',
|
||||||
|
_id: uuid(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_nye2017'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_nye2017',
|
||||||
|
_id: uuid(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_nye2016'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_nye2016',
|
||||||
|
_id: uuid(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_nye2015'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_nye2015',
|
||||||
|
_id: uuid(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_nye2014'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_nye2014',
|
||||||
|
_id: uuid(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
set['items.gear.owned.head_special_nye'] = false;
|
||||||
|
push = [
|
||||||
|
{
|
||||||
|
type: 'marketGear',
|
||||||
|
path: 'gear.flat.head_special_nye',
|
||||||
|
_id: uuid(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
88
migrations/archive/2019/20190131_habit_birthday.js
Normal file
88
migrations/archive/2019/20190131_habit_birthday.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20190131_habit_birthday';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
import { model as User } from '../../../website/server/models/user';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const inc = {
|
||||||
|
'items.food.Cake_Skeleton': 1,
|
||||||
|
'items.food.Cake_Base': 1,
|
||||||
|
'items.food.Cake_CottonCandyBlue': 1,
|
||||||
|
'items.food.Cake_CottonCandyPink': 1,
|
||||||
|
'items.food.Cake_Shade': 1,
|
||||||
|
'items.food.Cake_White': 1,
|
||||||
|
'items.food.Cake_Golden': 1,
|
||||||
|
'items.food.Cake_Zombie': 1,
|
||||||
|
'items.food.Cake_Desert': 1,
|
||||||
|
'items.food.Cake_Red': 1,
|
||||||
|
'achievements.habitBirthdays': 1,
|
||||||
|
};
|
||||||
|
const set = {};
|
||||||
|
let push;
|
||||||
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.armor_special_birthday2018 !== 'undefined') {
|
||||||
|
set['items.gear.owned.armor_special_birthday2019'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2019', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_birthday2017 !== 'undefined') {
|
||||||
|
set['items.gear.owned.armor_special_birthday2018'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2018', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_birthday2016 !== 'undefined') {
|
||||||
|
set['items.gear.owned.armor_special_birthday2017'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2017', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_birthday2015 !== 'undefined') {
|
||||||
|
set['items.gear.owned.armor_special_birthday2016'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2016', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_birthday !== 'undefined') {
|
||||||
|
set['items.gear.owned.armor_special_birthday2015'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2015', _id: uuid()}};
|
||||||
|
} else {
|
||||||
|
set['items.gear.owned.armor_special_birthday'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday', _id: uuid()}};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
return await User.update({_id: user._id}, {$inc: inc, $set: set, $push: push}).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
'auth.timestamps.loggedin': {$gt: new Date('2019-01-15')},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
110
migrations/archive/mystery-items-old.js
Normal file
110
migrations/archive/mystery-items-old.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import monk from 'monk';
|
||||||
|
import nconf from 'nconf';
|
||||||
|
|
||||||
|
const migrationName = 'mystery-items-201808.js'; // Update per month
|
||||||
|
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Award this month's mystery items to subscribers
|
||||||
|
*/
|
||||||
|
const MYSTERY_ITEMS = ['armor_mystery_201810', 'head_mystery_201810'];
|
||||||
|
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||||
|
|
||||||
|
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||||
|
let UserNotification = require('../../website/server/models/userNotification').model;
|
||||||
|
|
||||||
|
function processUsers (lastId) {
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: migrationName},
|
||||||
|
'purchased.plan.customerId': { $ne: null },
|
||||||
|
$or: [
|
||||||
|
{ 'purchased.plan.dateTerminated': { $gte: new Date() } },
|
||||||
|
{ 'purchased.plan.dateTerminated': { $exists: false } },
|
||||||
|
{ 'purchased.plan.dateTerminated': { $eq: null } },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.find(query, {
|
||||||
|
sort: {_id: 1},
|
||||||
|
limit: 250,
|
||||||
|
fields: [
|
||||||
|
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, `ERROR! ${ err}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
function updateUsers (users) {
|
||||||
|
if (!users || users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
displayData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let userPromises = users.map(updateUser);
|
||||||
|
let lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(() => {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const addToSet = {
|
||||||
|
'purchased.plan.mysteryItems': {
|
||||||
|
$each: MYSTERY_ITEMS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const push = {
|
||||||
|
notifications: (new UserNotification({
|
||||||
|
type: 'NEW_MYSTERY_ITEMS',
|
||||||
|
data: {
|
||||||
|
MYSTERY_ITEMS,
|
||||||
|
},
|
||||||
|
})).toJSON(),
|
||||||
|
};
|
||||||
|
|
||||||
|
dbUsers.update({_id: user._id}, {$addToSet: addToSet, $push: push});
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
||||||
|
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayData () {
|
||||||
|
console.warn(`\n${ count } users processed\n`);
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exiting (code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) {
|
||||||
|
msg = 'ERROR!';
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
if (code) {
|
||||||
|
console.error(msg);
|
||||||
|
} else {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
@@ -17,7 +17,7 @@ function setUpServer () {
|
|||||||
setUpServer();
|
setUpServer();
|
||||||
|
|
||||||
// Replace this with your migration
|
// Replace this with your migration
|
||||||
const processUsers = require('../scripts/gdpr-delete-users.js');
|
const processUsers = require('./users/mystery-items.js');
|
||||||
processUsers()
|
processUsers()
|
||||||
.then(function success () {
|
.then(function success () {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
const MIGRATION_NAME = '20181023_veteran_pet_ladder';
|
|
||||||
import { model as User } from '../../website/server/models/user';
|
|
||||||
|
|
||||||
function processUsers (lastId) {
|
|
||||||
let query = {
|
|
||||||
migration: {$ne: MIGRATION_NAME},
|
|
||||||
'flags.verifiedUsername': true,
|
|
||||||
};
|
|
||||||
|
|
||||||
let fields = {
|
|
||||||
'items.pets': 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (lastId) {
|
|
||||||
query._id = {
|
|
||||||
$gt: lastId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return User.find(query)
|
|
||||||
.limit(250)
|
|
||||||
.sort({_id: 1})
|
|
||||||
.select(fields)
|
|
||||||
.then(updateUsers)
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
return exiting(1, `ERROR! ${err}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let progressCount = 1000;
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
function updateUsers (users) {
|
|
||||||
if (!users || users.length === 0) {
|
|
||||||
console.warn('All appropriate users found and modified.');
|
|
||||||
displayData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
|
||||||
let lastUser = users[users.length - 1];
|
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
|
||||||
.then(() => {
|
|
||||||
processUsers(lastUser._id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateUser (user) {
|
|
||||||
count++;
|
|
||||||
|
|
||||||
let set = {migration: MIGRATION_NAME};
|
|
||||||
|
|
||||||
if (user.items.pets['Bear-Veteran']) {
|
|
||||||
set['items.pets.Fox-Veteran'] = 5;
|
|
||||||
} else if (user.items.pets['Lion-Veteran']) {
|
|
||||||
set['items.pets.Bear-Veteran'] = 5;
|
|
||||||
} else if (user.items.pets['Tiger-Veteran']) {
|
|
||||||
set['items.pets.Lion-Veteran'] = 5;
|
|
||||||
} else if (user.items.pets['Wolf-Veteran']) {
|
|
||||||
set['items.pets.Tiger-Veteran'] = 5;
|
|
||||||
} else {
|
|
||||||
set['items.pets.Wolf-Veteran'] = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
|
||||||
|
|
||||||
return user.update({_id: user._id}, {$set: set}).exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayData () {
|
|
||||||
console.warn(`\n${count} users processed\n`);
|
|
||||||
return exiting(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function exiting (code, msg) {
|
|
||||||
code = code || 0; // 0 = success
|
|
||||||
if (code && !msg) {
|
|
||||||
msg = 'ERROR!';
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
if (code) {
|
|
||||||
console.error(msg);
|
|
||||||
} else {
|
|
||||||
console.log(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
process.exit(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = processUsers;
|
|
||||||
61
migrations/users/bulk-email.js
Normal file
61
migrations/users/bulk-email.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import { sendTxn } from '../../website/server/libs/email';
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
import moment from 'moment';
|
||||||
|
import nconf from 'nconf';
|
||||||
|
const BASE_URL = nconf.get('BASE_URL');
|
||||||
|
const EMAIL_SLUG = 'mandrill-email-slug'; // Set email template to send
|
||||||
|
const MIGRATION_NAME = 'bulk-email';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
sendTxn(
|
||||||
|
user,
|
||||||
|
EMAIL_SLUG,
|
||||||
|
[{name: 'BASE_URL', content: BASE_URL}] // Add variables from template
|
||||||
|
);
|
||||||
|
|
||||||
|
return await User.update({_id: user._id}, {$set: {migration: MIGRATION_NAME}}).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
'auth.timestamps.loggedin': {$gt: moment().subtract(2, 'weeks').toDate()}, // customize or remove to target different populations
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
auth: 1,
|
||||||
|
preferences: 1,
|
||||||
|
profile: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,67 +1,24 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = 'full-stable';
|
||||||
import each from 'lodash/each';
|
import each from 'lodash/each';
|
||||||
import keys from 'lodash/keys';
|
import keys from 'lodash/keys';
|
||||||
import content from '../../website/common/script/content/index';
|
import content from '../../website/common/script/content/index';
|
||||||
const migrationName = 'full-stable.js';
|
|
||||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
import { model as User } from '../../website/server/models/user';
|
||||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Award users every extant pet and mount
|
* Award users every extant pet and mount
|
||||||
*/
|
*/
|
||||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
|
||||||
|
|
||||||
let monk = require('monk');
|
async function updateUser (user) {
|
||||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
|
||||||
|
|
||||||
function processUsers (lastId) {
|
|
||||||
// specify a query to limit the affected users (empty for all users):
|
|
||||||
let query = {
|
|
||||||
'profile.name': 'SabreCat',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (lastId) {
|
|
||||||
query._id = {
|
|
||||||
$gt: lastId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
dbUsers.find(query, {
|
|
||||||
sort: {_id: 1},
|
|
||||||
limit: 250,
|
|
||||||
fields: [
|
|
||||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
|
||||||
})
|
|
||||||
.then(updateUsers)
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let progressCount = 1000;
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
function updateUsers (users) {
|
|
||||||
if (!users || users.length === 0) {
|
|
||||||
console.warn('All appropriate users found and modified.');
|
|
||||||
displayData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
|
||||||
let lastUser = users[users.length - 1];
|
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
|
||||||
.then(() => {
|
|
||||||
processUsers(lastUser._id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateUser (user) {
|
|
||||||
count++;
|
count++;
|
||||||
let set = {
|
|
||||||
migration: migrationName,
|
const set = {};
|
||||||
};
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
each(keys(content.pets), (pet) => {
|
each(keys(content.pets), (pet) => {
|
||||||
set[`items.pets.${pet}`] = 5;
|
set[`items.pets.${pet}`] = 5;
|
||||||
@@ -88,30 +45,40 @@ function updateUser (user) {
|
|||||||
set[`items.mounts.${mount}`] = true;
|
set[`items.mounts.${mount}`] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
dbUsers.update({_id: user._id}, {$set: set});
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
module.exports = async function processUsers () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
let query = {
|
||||||
return exiting(0);
|
migration: {$ne: MIGRATION_NAME},
|
||||||
}
|
'auth.local.username': 'olson22',
|
||||||
|
};
|
||||||
|
|
||||||
function exiting (code, msg) {
|
const fields = {
|
||||||
code = code || 0; // 0 = success
|
_id: 1,
|
||||||
if (code && !msg) {
|
};
|
||||||
msg = 'ERROR!';
|
|
||||||
}
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
if (msg) {
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
if (code) {
|
.find(query)
|
||||||
console.error(msg);
|
.limit(250)
|
||||||
} else {
|
.sort({_id: 1})
|
||||||
console.log(msg);
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
process.exit(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = processUsers;
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,70 +1,13 @@
|
|||||||
import monk from 'monk';
|
/* eslint-disable no-console */
|
||||||
import nconf from 'nconf';
|
const MIGRATION_NAME = 'mystery_items_201904';
|
||||||
|
const MYSTERY_ITEMS = ['armor_mystery_201904', 'head_mystery_201904'];
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
import { model as UserNotification } from '../../website/server/models/userNotification';
|
||||||
|
|
||||||
const migrationName = 'mystery-items-201808.js'; // Update per month
|
const progressCount = 1000;
|
||||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
|
||||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Award this month's mystery items to subscribers
|
|
||||||
*/
|
|
||||||
const MYSTERY_ITEMS = ['armor_mystery_201810', 'head_mystery_201810'];
|
|
||||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
|
||||||
|
|
||||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
|
||||||
let UserNotification = require('../../website/server/models/userNotification').model;
|
|
||||||
|
|
||||||
function processUsers (lastId) {
|
|
||||||
// specify a query to limit the affected users (empty for all users):
|
|
||||||
let query = {
|
|
||||||
migration: {$ne: migrationName},
|
|
||||||
'purchased.plan.customerId': { $ne: null },
|
|
||||||
$or: [
|
|
||||||
{ 'purchased.plan.dateTerminated': { $gte: new Date() } },
|
|
||||||
{ 'purchased.plan.dateTerminated': { $exists: false } },
|
|
||||||
{ 'purchased.plan.dateTerminated': { $eq: null } },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (lastId) {
|
|
||||||
query._id = {
|
|
||||||
$gt: lastId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
dbUsers.find(query, {
|
|
||||||
sort: {_id: 1},
|
|
||||||
limit: 250,
|
|
||||||
fields: [
|
|
||||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
|
||||||
})
|
|
||||||
.then(updateUsers)
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let progressCount = 1000;
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
async function updateUser (user) {
|
||||||
if (!users || users.length === 0) {
|
|
||||||
console.warn('All appropriate users found and modified.');
|
|
||||||
displayData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
|
||||||
let lastUser = users[users.length - 1];
|
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
|
||||||
.then(() => {
|
|
||||||
processUsers(lastUser._id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateUser (user) {
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
const addToSet = {
|
const addToSet = {
|
||||||
@@ -80,31 +23,49 @@ function updateUser (user) {
|
|||||||
},
|
},
|
||||||
})).toJSON(),
|
})).toJSON(),
|
||||||
};
|
};
|
||||||
|
const set = {
|
||||||
|
migration: MIGRATION_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
dbUsers.update({_id: user._id}, {$addToSet: addToSet, $push: push});
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
return await User.update({_id: user._id}, {$set: set, $push: push, $addToSet: addToSet}).exec();
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
module.exports = async function processUsers () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
let query = {
|
||||||
return exiting(0);
|
migration: {$ne: MIGRATION_NAME},
|
||||||
}
|
'purchased.plan.customerId': { $ne: null },
|
||||||
|
$or: [
|
||||||
|
{ 'purchased.plan.dateTerminated': { $gte: new Date() } },
|
||||||
|
{ 'purchased.plan.dateTerminated': { $exists: false } },
|
||||||
|
{ 'purchased.plan.dateTerminated': { $eq: null } },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
function exiting (code, msg) {
|
const fields = {
|
||||||
code = code || 0; // 0 = success
|
_id: 1,
|
||||||
if (code && !msg) {
|
};
|
||||||
msg = 'ERROR!';
|
|
||||||
}
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
if (msg) {
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
if (code) {
|
.find(query)
|
||||||
console.error(msg);
|
.limit(250)
|
||||||
} else {
|
.sort({_id: 1})
|
||||||
console.log(msg);
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
process.exit(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = processUsers;
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
73
migrations/users/pi-day.js
Normal file
73
migrations/users/pi-day.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20190314_pi_day';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const inc = {
|
||||||
|
'items.food.Pie_Skeleton': 1,
|
||||||
|
'items.food.Pie_Base': 1,
|
||||||
|
'items.food.Pie_CottonCandyBlue': 1,
|
||||||
|
'items.food.Pie_CottonCandyPink': 1,
|
||||||
|
'items.food.Pie_Shade': 1,
|
||||||
|
'items.food.Pie_White': 1,
|
||||||
|
'items.food.Pie_Golden': 1,
|
||||||
|
'items.food.Pie_Zombie': 1,
|
||||||
|
'items.food.Pie_Desert': 1,
|
||||||
|
'items.food.Pie_Red': 1,
|
||||||
|
};
|
||||||
|
const set = {};
|
||||||
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
|
set['items.gear.owned.head_special_piDay'] = false;
|
||||||
|
set['items.gear.owned.shield_special_piDay'] = false;
|
||||||
|
const push = [
|
||||||
|
{type: 'marketGear', path: 'gear.flat.head_special_piDay', _id: uuid()},
|
||||||
|
{type: 'marketGear', path: 'gear.flat.shield_special_piDay', _id: uuid()},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
return await User.update({_id: user._id}, {$inc: inc, $set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
'auth.timestamps.loggedin': {$gt: new Date('2019-02-15')},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
81
migrations/users/take-this.js
Normal file
81
migrations/users/take-this.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20181203_take_this';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
const set = {};
|
||||||
|
let push;
|
||||||
|
|
||||||
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.back_special_takeThis !== 'undefined') {
|
||||||
|
push = false;
|
||||||
|
} else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') {
|
||||||
|
set['items.gear.owned.back_special_takeThis'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.back_special_takeThis', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
||||||
|
set['items.gear.owned.body_special_takeThis'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_takeThis', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
||||||
|
set['items.gear.owned.head_special_takeThis'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_takeThis', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
||||||
|
set['items.gear.owned.armor_special_takeThis'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_takeThis', _id: uuid()}};
|
||||||
|
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
||||||
|
set['items.gear.owned.weapon_special_takeThis'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', _id: uuid()}};
|
||||||
|
} else {
|
||||||
|
set['items.gear.owned.shield_special_takeThis'] = false;
|
||||||
|
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.shield_special_takeThis', _id: uuid()}};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
if (push) {
|
||||||
|
return await User.update({_id: user._id}, {$set: set, $push: push}).exec();
|
||||||
|
} else {
|
||||||
|
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: {$ne: MIGRATION_NAME},
|
||||||
|
challenges: '00708425-d477-41a5-bf27-6270466e7976',
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
7674
package-lock.json
generated
7674
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
81
package.json
81
package.json
@@ -1,17 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||||
"version": "4.69.1",
|
"version": "4.93.3",
|
||||||
"main": "./website/server/index.js",
|
"main": "./website/server/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@google-cloud/trace-agent": "^3.6.0",
|
||||||
"@slack/client": "^3.8.1",
|
"@slack/client": "^3.8.1",
|
||||||
"accepts": "^1.3.5",
|
"accepts": "^1.3.5",
|
||||||
"amazon-payments": "^0.2.7",
|
"amazon-payments": "^0.2.7",
|
||||||
"amplitude": "^3.5.0",
|
"amplitude": "^3.5.0",
|
||||||
|
"amplitude-js": "^5.0.0",
|
||||||
"apidoc": "^0.17.5",
|
"apidoc": "^0.17.5",
|
||||||
"apn": "^2.2.0",
|
"apn": "^2.2.0",
|
||||||
"autoprefixer": "^8.5.0",
|
"autoprefixer": "^9.4.0",
|
||||||
"aws-sdk": "^2.329.0",
|
"aws-sdk": "^2.432.0",
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.0",
|
||||||
"axios-progress-bar": "^1.2.0",
|
"axios-progress-bar": "^1.2.0",
|
||||||
"babel-core": "^6.26.3",
|
"babel-core": "^6.26.3",
|
||||||
@@ -26,16 +28,16 @@
|
|||||||
"babel-preset-es2015": "^6.6.0",
|
"babel-preset-es2015": "^6.6.0",
|
||||||
"babel-register": "^6.6.0",
|
"babel-register": "^6.6.0",
|
||||||
"babel-runtime": "^6.11.6",
|
"babel-runtime": "^6.11.6",
|
||||||
"bcrypt": "^3.0.1",
|
"bcrypt": "^3.0.5",
|
||||||
"body-parser": "^1.18.3",
|
"body-parser": "^1.18.3",
|
||||||
"bootstrap": "^4.1.1",
|
"bootstrap": "^4.1.1",
|
||||||
"bootstrap-vue": "^2.0.0-rc.9",
|
"bootstrap-vue": "^2.0.0-rc.18",
|
||||||
"compression": "^1.7.2",
|
"compression": "^1.7.4",
|
||||||
"cookie-session": "^1.2.0",
|
"cookie-session": "^1.3.3",
|
||||||
"coupon-code": "^0.4.5",
|
"coupon-code": "^0.4.5",
|
||||||
"cross-env": "^5.1.5",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^0.28.11",
|
"css-loader": "^0.28.11",
|
||||||
"csv-stringify": "^4.3.1",
|
"csv-stringify": "^5.1.0",
|
||||||
"cwait": "^1.1.1",
|
"cwait": "^1.1.1",
|
||||||
"domain-middleware": "~0.1.0",
|
"domain-middleware": "~0.1.0",
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.3",
|
||||||
@@ -46,14 +48,14 @@
|
|||||||
"got": "^9.0.0",
|
"got": "^9.0.0",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"gulp-babel": "^7.0.1",
|
"gulp-babel": "^7.0.1",
|
||||||
"gulp-imagemin": "^4.1.0",
|
"gulp-imagemin": "^5.0.3",
|
||||||
"gulp-nodemon": "^2.2.1",
|
"gulp-nodemon": "^2.4.1",
|
||||||
"gulp.spritesmith": "^6.9.0",
|
"gulp.spritesmith": "^6.9.0",
|
||||||
"habitica-markdown": "^1.3.0",
|
"habitica-markdown": "^1.3.0",
|
||||||
"hellojs": "^1.15.1",
|
"hellojs": "^1.18.1",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"image-size": "^0.6.2",
|
"image-size": "^0.7.0",
|
||||||
"in-app-purchase": "^1.10.2",
|
"in-app-purchase": "^1.11.3",
|
||||||
"intro.js": "^2.9.3",
|
"intro.js": "^2.9.3",
|
||||||
"jquery": ">=3.0.0",
|
"jquery": ">=3.0.0",
|
||||||
"js2xmlparser": "^3.0.0",
|
"js2xmlparser": "^3.0.0",
|
||||||
@@ -62,13 +64,13 @@
|
|||||||
"method-override": "^3.0.0",
|
"method-override": "^3.0.0",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
"moment-recur": "^1.0.7",
|
"moment-recur": "^1.0.7",
|
||||||
"mongoose": "^5.3.4",
|
"mongoose": "^5.4.19",
|
||||||
"morgan": "^1.7.0",
|
"morgan": "^1.7.0",
|
||||||
"nconf": "^0.10.0",
|
"nconf": "^0.10.0",
|
||||||
"node-gcm": "^1.0.2",
|
"node-gcm": "^1.0.2",
|
||||||
"node-sass": "^4.9.0",
|
"node-sass": "^4.9.0",
|
||||||
"nodemailer": "^4.6.4",
|
"nodemailer": "^6.0.0",
|
||||||
"ora": "^2.1.0",
|
"ora": "^3.2.0",
|
||||||
"pageres": "^4.1.1",
|
"pageres": "^4.1.1",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
"passport-facebook": "^2.0.0",
|
"passport-facebook": "^2.0.0",
|
||||||
@@ -80,17 +82,17 @@
|
|||||||
"ps-tree": "^1.0.0",
|
"ps-tree": "^1.0.0",
|
||||||
"pug": "^2.0.3",
|
"pug": "^2.0.3",
|
||||||
"rimraf": "^2.4.3",
|
"rimraf": "^2.4.3",
|
||||||
"sass-loader": "^7.0.0",
|
"sass-loader": "^7.0.3",
|
||||||
"shelljs": "^0.8.2",
|
"shelljs": "^0.8.2",
|
||||||
"short-uuid": "^3.0.0",
|
"short-uuid": "^3.0.0",
|
||||||
"smartbanner.js": "^1.9.1",
|
"smartbanner.js": "^1.11.0",
|
||||||
"stripe": "^5.9.0",
|
"stripe": "^5.9.0",
|
||||||
"superagent": "^3.8.3",
|
"superagent": "^5.0.2",
|
||||||
"svg-inline-loader": "^0.8.0",
|
"svg-inline-loader": "^0.8.0",
|
||||||
"svg-url-loader": "^2.3.2",
|
"svg-url-loader": "^2.3.2",
|
||||||
"svgo": "^1.0.5",
|
"svgo": "^1.2.0",
|
||||||
"svgo-loader": "^2.1.0",
|
"svgo-loader": "^2.1.0",
|
||||||
"universal-analytics": "^0.4.16",
|
"universal-analytics": "^0.4.17",
|
||||||
"update": "^0.7.4",
|
"update": "^0.7.4",
|
||||||
"upgrade": "^1.1.0",
|
"upgrade": "^1.1.0",
|
||||||
"url-loader": "^1.0.0",
|
"url-loader": "^1.0.0",
|
||||||
@@ -98,24 +100,24 @@
|
|||||||
"uuid": "^3.0.1",
|
"uuid": "^3.0.1",
|
||||||
"validator": "^10.5.0",
|
"validator": "^10.5.0",
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vue": "^2.5.16",
|
"vue": "^2.6.10",
|
||||||
"vue-loader": "^14.2.2",
|
"vue-loader": "^14.2.2",
|
||||||
"vue-mugen-scroll": "^0.2.1",
|
"vue-mugen-scroll": "^0.2.1",
|
||||||
"vue-router": "^3.0.0",
|
"vue-router": "^3.0.0",
|
||||||
"vue-style-loader": "^4.1.0",
|
"vue-style-loader": "^4.1.0",
|
||||||
"vue-template-compiler": "^2.5.16",
|
"vue-template-compiler": "^2.6.10",
|
||||||
"vuedraggable": "^2.15.0",
|
"vuedraggable": "^2.20.0",
|
||||||
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",
|
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",
|
||||||
"webpack": "^3.12.0",
|
"webpack": "^3.12.0",
|
||||||
"webpack-merge": "^4.0.0",
|
"webpack-merge": "^4.1.3",
|
||||||
"winston": "^2.4.2",
|
"winston": "^2.4.3",
|
||||||
"winston-loggly-bulk": "^2.0.2",
|
"winston-loggly-bulk": "^2.0.2",
|
||||||
"xml2js": "^0.4.4"
|
"xml2js": "^0.4.4"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^8.9.4",
|
"node": "^10",
|
||||||
"npm": "^5.6.0"
|
"npm": "^6"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint --ext .js,.vue .",
|
"lint": "eslint --ext .js,.vue .",
|
||||||
@@ -144,15 +146,15 @@
|
|||||||
"apidoc": "gulp apidoc"
|
"apidoc": "gulp apidoc"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/test-utils": "^1.0.0-beta.16",
|
"@vue/test-utils": "^1.0.0-beta.29",
|
||||||
"babel-plugin-istanbul": "^4.1.6",
|
"babel-plugin-istanbul": "^4.1.6",
|
||||||
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"chalk": "^2.4.1",
|
"chalk": "^2.4.1",
|
||||||
"chromedriver": "^2.38.3",
|
"chromedriver": "^2.40.0",
|
||||||
"connect-history-api-fallback": "^1.1.0",
|
"connect-history-api-fallback": "^1.1.0",
|
||||||
"coveralls": "^3.0.1",
|
"coveralls": "^3.0.3",
|
||||||
"cross-spawn": "^6.0.5",
|
"cross-spawn": "^6.0.5",
|
||||||
"eslint": "^4.19.1",
|
"eslint": "^4.19.1",
|
||||||
"eslint-config-habitrpg": "^4.0.0",
|
"eslint-config-habitrpg": "^4.0.0",
|
||||||
@@ -162,9 +164,9 @@
|
|||||||
"eslint-plugin-mocha": "^5.0.0",
|
"eslint-plugin-mocha": "^5.0.0",
|
||||||
"eventsource-polyfill": "^0.9.6",
|
"eventsource-polyfill": "^0.9.6",
|
||||||
"expect.js": "^0.3.1",
|
"expect.js": "^0.3.1",
|
||||||
"http-proxy-middleware": "^0.18.0",
|
"http-proxy-middleware": "^0.19.0",
|
||||||
"istanbul": "^1.1.0-alpha.1",
|
"istanbul": "^1.1.0-alpha.1",
|
||||||
"karma": "^3.0.0",
|
"karma": "^4.0.1",
|
||||||
"karma-babel-preprocessor": "^7.0.0",
|
"karma-babel-preprocessor": "^7.0.0",
|
||||||
"karma-chai-plugins": "^0.9.0",
|
"karma-chai-plugins": "^0.9.0",
|
||||||
"karma-chrome-launcher": "^2.2.0",
|
"karma-chrome-launcher": "^2.2.0",
|
||||||
@@ -179,19 +181,16 @@
|
|||||||
"lcov-result-merger": "^3.0.0",
|
"lcov-result-merger": "^3.0.0",
|
||||||
"mocha": "^5.1.1",
|
"mocha": "^5.1.1",
|
||||||
"monk": "^6.0.6",
|
"monk": "^6.0.6",
|
||||||
"nightwatch": "^0.9.21",
|
"nightwatch": "^1.0.16",
|
||||||
"puppeteer": "^1.4.0",
|
"puppeteer": "^1.14.0",
|
||||||
"require-again": "^2.0.0",
|
"require-again": "^2.0.0",
|
||||||
"selenium-server": "^3.12.0",
|
"selenium-server": "^3.12.0",
|
||||||
"sinon": "^4.5.0",
|
"sinon": "^7.2.4",
|
||||||
"sinon-chai": "^3.0.0",
|
"sinon-chai": "^3.0.0",
|
||||||
"sinon-stub-promise": "^4.0.0",
|
"sinon-stub-promise": "^4.0.0",
|
||||||
"webpack-bundle-analyzer": "^2.12.0",
|
"webpack-bundle-analyzer": "^2.12.0",
|
||||||
"webpack-dev-middleware": "^2.0.5",
|
"webpack-dev-middleware": "^2.0.5",
|
||||||
"webpack-hot-middleware": "^2.22.2"
|
"webpack-hot-middleware": "^2.22.2"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {}
|
||||||
"memwatch-next": "^0.3.0",
|
|
||||||
"node-rdkafka": "^2.3.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ async function _deleteAmplitudeData (userId, email) {
|
|||||||
if (response) console.log(`${response.status} ${response.statusText}`);
|
if (response) console.log(`${response.status} ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _deleteHabiticaData (user) {
|
async function _deleteHabiticaData (user, email) {
|
||||||
await User.update(
|
await User.update(
|
||||||
{_id: user._id},
|
{_id: user._id},
|
||||||
{$set: {
|
{$set: {
|
||||||
'auth.local.passwordHashMethod': 'bcrypt',
|
'auth.local.email': email,
|
||||||
'auth.local.hashed_password': '$2a$10$QDnNh1j1yMPnTXDEOV38xOePEWFd4X8DSYwAM8XTmqmacG5X0DKjW',
|
'auth.local.hashed_password': '$2a$10$QDnNh1j1yMPnTXDEOV38xOePEWFd4X8DSYwAM8XTmqmacG5X0DKjW',
|
||||||
|
'auth.local.passwordHashMethod': 'bcrypt',
|
||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
const response = await axios.delete(
|
const response = await axios.delete(
|
||||||
@@ -52,7 +53,7 @@ async function _deleteHabiticaData (user) {
|
|||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
console.log(`${response.status} ${response.statusText}`);
|
console.log(`${response.status} ${response.statusText}`);
|
||||||
if (response.status === 200) console.log(`${user._id} removed. Last login: ${user.auth.timestamps.loggedin}`);
|
if (response.status === 200) console.log(`${user._id} (${email}) removed. Last login: ${user.auth.timestamps.loggedin}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ async function _processEmailAddress (email) {
|
|||||||
} else {
|
} else {
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
await _deleteAmplitudeData(user._id, email); // eslint-disable-line no-await-in-loop
|
await _deleteAmplitudeData(user._id, email); // eslint-disable-line no-await-in-loop
|
||||||
await _deleteHabiticaData(user); // eslint-disable-line no-await-in-loop
|
await _deleteHabiticaData(user, email); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,28 +12,27 @@ const nconf = require('nconf');
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const paypal = require('paypal-rest-sdk');
|
const paypal = require('paypal-rest-sdk');
|
||||||
const blocks = require('../website/common').content.subscriptionBlocks;
|
const blocks = require('../website/common').content.subscriptionBlocks;
|
||||||
const live = nconf.get('PAYPAL:mode') === 'live';
|
const live = nconf.get('PAYPAL_MODE') === 'live';
|
||||||
|
|
||||||
nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json')));
|
nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json')));
|
||||||
|
|
||||||
let OP = 'create'; // list create update remove
|
let OP = 'create'; // list get update create create-webprofile
|
||||||
|
|
||||||
paypal.configure({
|
paypal.configure({
|
||||||
mode: nconf.get('PAYPAL:mode'), // sandbox or live
|
mode: nconf.get('PAYPAL_MODE'), // sandbox or live
|
||||||
client_id: nconf.get('PAYPAL:client_id'),
|
client_id: nconf.get('PAYPAL_CLIENT_ID'),
|
||||||
client_secret: nconf.get('PAYPAL:client_secret'),
|
client_secret: nconf.get('PAYPAL_CLIENT_SECRET'),
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://developer.paypal.com/docs/api/#billing-plans-and-agreements
|
// https://developer.paypal.com/docs/api/#billing-plans-and-agreements
|
||||||
let billingPlanTitle = 'Habitica Subscription';
|
let billingPlanTitle = 'Habitica Subscription';
|
||||||
let billingPlanAttributes = {
|
let billingPlanAttributes = {
|
||||||
name: billingPlanTitle,
|
|
||||||
description: billingPlanTitle,
|
description: billingPlanTitle,
|
||||||
type: 'INFINITE',
|
type: 'INFINITE',
|
||||||
merchant_preferences: {
|
merchant_preferences: {
|
||||||
auto_bill_amount: 'yes',
|
auto_bill_amount: 'yes',
|
||||||
cancel_url: live ? 'https://habitica.com' : 'http://localhost:3000',
|
cancel_url: live ? 'https://habitica.com' : 'http://localhost:3000',
|
||||||
return_url: `${live ? 'https://habitica.com' : 'http://localhost:3000' }/paypal/subscribe/success`,
|
return_url: `${live ? 'https://habitica.com' : 'http://localhost:3000'}/paypal/subscribe/success`,
|
||||||
},
|
},
|
||||||
payment_definitions: [{
|
payment_definitions: [{
|
||||||
type: 'REGULAR',
|
type: 'REGULAR',
|
||||||
@@ -45,7 +44,7 @@ let billingPlanAttributes = {
|
|||||||
_.each(blocks, (block) => {
|
_.each(blocks, (block) => {
|
||||||
block.definition = _.cloneDeep(billingPlanAttributes);
|
block.definition = _.cloneDeep(billingPlanAttributes);
|
||||||
_.merge(block.definition.payment_definitions[0], {
|
_.merge(block.definition.payment_definitions[0], {
|
||||||
name: `${billingPlanTitle } ($${block.price} every ${block.months} months, recurring)`,
|
name: `${billingPlanTitle} ($${block.price} every ${block.months} months, recurring)`,
|
||||||
frequency_interval: `${block.months}`,
|
frequency_interval: `${block.months}`,
|
||||||
amount: {
|
amount: {
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
@@ -63,7 +62,7 @@ switch (OP) {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'get':
|
case 'get':
|
||||||
paypal.billingPlan.get(nconf.get('PAYPAL:billing_plans:12'), (err, plan) => {
|
paypal.billingPlan.get(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), (err, plan) => {
|
||||||
console.log({err, plan});
|
console.log({err, plan});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@@ -75,7 +74,7 @@ switch (OP) {
|
|||||||
cancel_url: 'https://habitica.com',
|
cancel_url: 'https://habitica.com',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
paypal.billingPlan.update(nconf.get('PAYPAL:billing_plans:12'), updatePayload, (err, res) => {
|
paypal.billingPlan.update(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), updatePayload, (err, res) => {
|
||||||
console.log({err, plan: res});
|
console.log({err, plan: res});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@@ -101,9 +100,6 @@ switch (OP) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove': break;
|
|
||||||
|
|
||||||
case 'create-webprofile':
|
case 'create-webprofile':
|
||||||
let webexpinfo = {
|
let webexpinfo = {
|
||||||
name: 'HabiticaProfile',
|
name: 'HabiticaProfile',
|
||||||
@@ -116,4 +112,4 @@ switch (OP) {
|
|||||||
console.log(error, result);
|
console.log(error, result);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
For information about writing and running tests, see [Using Your Local Install to Modify Habitica's Website and API](http://habitica.wikia.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API).
|
For information about writing and running tests, see [Using Your Local Install to Modify Habitica's Website and API](http://habitica.fandom.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API).
|
||||||
|
|||||||
@@ -335,14 +335,13 @@ describe('analyticsService', () => {
|
|||||||
let data, itemSpy;
|
let data, itemSpy;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
Visitor.prototype.event.yields();
|
||||||
|
|
||||||
itemSpy = sandbox.stub().returnsThis();
|
itemSpy = sandbox.stub().returnsThis();
|
||||||
|
|
||||||
Visitor.prototype.event.returns({
|
|
||||||
send: sandbox.stub(),
|
|
||||||
});
|
|
||||||
Visitor.prototype.transaction.returns({
|
Visitor.prototype.transaction.returns({
|
||||||
item: itemSpy,
|
item: itemSpy,
|
||||||
send: sandbox.stub().returnsThis(),
|
send: sandbox.stub().yields(),
|
||||||
});
|
});
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import {
|
|||||||
BadRequest,
|
BadRequest,
|
||||||
InternalServerError,
|
InternalServerError,
|
||||||
NotFound,
|
NotFound,
|
||||||
|
NotificationNotFound,
|
||||||
} from '../../../../website/server/libs/errors';
|
} from '../../../../website/server/libs/errors';
|
||||||
|
import i18n from '../../../../website/common/script/i18n';
|
||||||
|
|
||||||
describe('Custom Errors', () => {
|
describe('Custom Errors', () => {
|
||||||
describe('CustomError', () => {
|
describe('CustomError', () => {
|
||||||
@@ -66,6 +68,23 @@ describe('Custom Errors', () => {
|
|||||||
|
|
||||||
expect(notAuthorizedError.message).to.eql('Custom Error Message');
|
expect(notAuthorizedError.message).to.eql('Custom Error Message');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('NotificationNotFound', () => {
|
||||||
|
it('is an instance of NotFound', () => {
|
||||||
|
const notificationNotFoundErr = new NotificationNotFound();
|
||||||
|
expect(notificationNotFoundErr).to.be.an.instanceOf(NotFound);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('it returns an http code of 404', () => {
|
||||||
|
const notificationNotFoundErr = new NotificationNotFound();
|
||||||
|
expect(notificationNotFoundErr.httpCode).to.eql(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a standard message', () => {
|
||||||
|
const notificationNotFoundErr = new NotificationNotFound();
|
||||||
|
expect(notificationNotFoundErr.message).to.eql(i18n.t('messageNotificationNotFound'));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('BadRequest', () => {
|
describe('BadRequest', () => {
|
||||||
|
|||||||
113
test/api/unit/libs/items/utils.test.js
Normal file
113
test/api/unit/libs/items/utils.test.js
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
import {
|
||||||
|
validateItemPath,
|
||||||
|
getDefaultOwnedGear,
|
||||||
|
castItemVal,
|
||||||
|
} from '../../../../../website/server/libs/items/utils';
|
||||||
|
|
||||||
|
describe('Items Utils', () => {
|
||||||
|
describe('getDefaultOwnedGear', () => {
|
||||||
|
it('clones the result object', () => {
|
||||||
|
const res1 = getDefaultOwnedGear();
|
||||||
|
res1.extraProperty = true;
|
||||||
|
|
||||||
|
const res2 = getDefaultOwnedGear();
|
||||||
|
expect(res2).not.to.have.property('extraProperty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateItemPath', () => {
|
||||||
|
it('returns false if not an item path', () => {
|
||||||
|
expect(validateItemPath('notitems.gear.owned.item')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true if a valid schema path', () => {
|
||||||
|
expect(validateItemPath('items.gear.equipped.weapon')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.currentPet')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.special.snowball')).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with owned gear paths', () => {
|
||||||
|
expect(validateItemPath('items.gear.owned.head_armoire_crownOfHearts')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.gear.owned.head_invalid')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with pets paths', () => {
|
||||||
|
expect(validateItemPath('items.pets.Wolf-CottonCandyPink')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.pets.Wolf-Invalid')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with eggs paths', () => {
|
||||||
|
expect(validateItemPath('items.eggs.LionCub')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.eggs.Armadillo')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.eggs.NotAnArmadillo')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with hatching potions paths', () => {
|
||||||
|
expect(validateItemPath('items.hatchingPotions.Base')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.hatchingPotions.StarryNight')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.hatchingPotions.Invalid')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with food paths', () => {
|
||||||
|
expect(validateItemPath('items.food.Cake_Base')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.food.Cake_Invalid')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with mounts paths', () => {
|
||||||
|
expect(validateItemPath('items.mounts.Cactus-Base')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.mounts.Aether-Invisible')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.mounts.Aether-Invalid')).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with quests paths', () => {
|
||||||
|
expect(validateItemPath('items.quests.atom3')).to.equal(true);
|
||||||
|
expect(validateItemPath('items.quests.invalid')).to.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('castItemVal', () => {
|
||||||
|
it('returns the item val untouched if not an item path', () => {
|
||||||
|
expect(castItemVal('notitems.gear.owned.item', 'a string')).to.equal('a string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the item val untouched if an unsupported path', () => {
|
||||||
|
expect(castItemVal('items.gear.equipped.weapon', 'a string')).to.equal('a string');
|
||||||
|
expect(castItemVal('items.currentPet', 'a string')).to.equal('a string');
|
||||||
|
expect(castItemVal('items.special.snowball', 'a string')).to.equal('a string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts values for pets paths to numbers', () => {
|
||||||
|
expect(castItemVal('items.pets.Wolf-CottonCandyPink', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.pets.Wolf-Invalid', '5')).to.equal(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts values for eggs paths to numbers', () => {
|
||||||
|
expect(castItemVal('items.eggs.LionCub', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.eggs.Armadillo', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.eggs.NotAnArmadillo', '5')).to.equal(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts values for hatching potions paths to numbers', () => {
|
||||||
|
expect(castItemVal('items.hatchingPotions.Base', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.hatchingPotions.StarryNight', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.hatchingPotions.Invalid', '5')).to.equal(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts values for food paths to numbers', () => {
|
||||||
|
expect(castItemVal('items.food.Cake_Base', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.food.Cake_Invalid', '5')).to.equal(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts values for mounts paths to numbers', () => {
|
||||||
|
expect(castItemVal('items.mounts.Cactus-Base', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.mounts.Aether-Invisible', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.mounts.Aether-Invalid', '5')).to.equal(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts values for quests paths to numbers', () => {
|
||||||
|
expect(castItemVal('items.quests.atom3', '5')).to.equal(5);
|
||||||
|
expect(castItemVal('items.quests.invalid', '5')).to.equal(5);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -245,7 +245,9 @@ describe('Password Utilities', () => {
|
|||||||
|
|
||||||
it('returns false if the user has no local auth', async () => {
|
it('returns false if the user has no local auth', async () => {
|
||||||
let user = await generateUser({
|
let user = await generateUser({
|
||||||
auth: 'not an object with valid fields',
|
auth: {
|
||||||
|
facebook: {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
|
|
||||||
function expectBillingAggreementDetailSpy () {
|
function expectBillingAggreementDetailSpy () {
|
||||||
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails')
|
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails')
|
||||||
.returnsPromise()
|
|
||||||
.resolves({
|
.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Open'},
|
BillingAgreementStatus: {State: 'Open'},
|
||||||
@@ -80,14 +79,14 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
headers = {};
|
headers = {};
|
||||||
|
|
||||||
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails');
|
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails');
|
||||||
getBillingAgreementDetailsSpy.returnsPromise().resolves({
|
getBillingAgreementDetailsSpy.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Closed'},
|
BillingAgreementStatus: {State: 'Closed'},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription');
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription');
|
||||||
paymentCancelSubscriptionSpy.returnsPromise().resolves({});
|
paymentCancelSubscriptionSpy.resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
@@ -118,7 +117,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should close a user subscription if amazon not closed', async () => {
|
it('should close a user subscription if amazon not closed', async () => {
|
||||||
amzLib.getBillingAgreementDetails.restore();
|
amzLib.getBillingAgreementDetails.restore();
|
||||||
expectBillingAggreementDetailSpy();
|
expectBillingAggreementDetailSpy();
|
||||||
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').returnsPromise().resolves({});
|
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
|
||||||
billingAgreementId = user.purchased.plan.customerId;
|
billingAgreementId = user.purchased.plan.customerId;
|
||||||
|
|
||||||
await amzLib.cancelSubscription({user, headers});
|
await amzLib.cancelSubscription({user, headers});
|
||||||
@@ -164,7 +163,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should close a group subscription if amazon not closed', async () => {
|
it('should close a group subscription if amazon not closed', async () => {
|
||||||
amzLib.getBillingAgreementDetails.restore();
|
amzLib.getBillingAgreementDetails.restore();
|
||||||
expectBillingAggreementDetailSpy();
|
expectBillingAggreementDetailSpy();
|
||||||
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').returnsPromise().resolves({});
|
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
|
||||||
billingAgreementId = group.purchased.plan.customerId;
|
billingAgreementId = group.purchased.plan.customerId;
|
||||||
|
|
||||||
await amzLib.cancelSubscription({user, groupId: group._id, headers});
|
await amzLib.cancelSubscription({user, groupId: group._id, headers});
|
||||||
|
|||||||
@@ -68,22 +68,22 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
orderReferenceId = 'orderReferenceId';
|
orderReferenceId = 'orderReferenceId';
|
||||||
|
|
||||||
setOrderReferenceDetailsSpy = sinon.stub(amzLib, 'setOrderReferenceDetails');
|
setOrderReferenceDetailsSpy = sinon.stub(amzLib, 'setOrderReferenceDetails');
|
||||||
setOrderReferenceDetailsSpy.returnsPromise().resolves({});
|
setOrderReferenceDetailsSpy.resolves({});
|
||||||
|
|
||||||
confirmOrderReferenceSpy = sinon.stub(amzLib, 'confirmOrderReference');
|
confirmOrderReferenceSpy = sinon.stub(amzLib, 'confirmOrderReference');
|
||||||
confirmOrderReferenceSpy.returnsPromise().resolves({});
|
confirmOrderReferenceSpy.resolves({});
|
||||||
|
|
||||||
authorizeSpy = sinon.stub(amzLib, 'authorize');
|
authorizeSpy = sinon.stub(amzLib, 'authorize');
|
||||||
authorizeSpy.returnsPromise().resolves({});
|
authorizeSpy.resolves({});
|
||||||
|
|
||||||
closeOrderReferenceSpy = sinon.stub(amzLib, 'closeOrderReference');
|
closeOrderReferenceSpy = sinon.stub(amzLib, 'closeOrderReference');
|
||||||
closeOrderReferenceSpy.returnsPromise().resolves({});
|
closeOrderReferenceSpy.resolves({});
|
||||||
|
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems');
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems');
|
||||||
paymentBuyGemsStub.returnsPromise().resolves({});
|
paymentBuyGemsStub.resolves({});
|
||||||
|
|
||||||
paymentCreateSubscritionStub = sinon.stub(payments, 'createSubscription');
|
paymentCreateSubscritionStub = sinon.stub(payments, 'createSubscription');
|
||||||
paymentCreateSubscritionStub.returnsPromise().resolves({});
|
paymentCreateSubscritionStub.resolves({});
|
||||||
|
|
||||||
sinon.stub(common, 'uuid').returns('uuid-generated');
|
sinon.stub(common, 'uuid').returns('uuid-generated');
|
||||||
});
|
});
|
||||||
@@ -111,7 +111,7 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('should purchase gems', async () => {
|
it('should purchase gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
await amzLib.checkout({user, orderReferenceId, headers});
|
await amzLib.checkout({user, orderReferenceId, headers});
|
||||||
|
|
||||||
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD);
|
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD);
|
||||||
@@ -140,7 +140,7 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should error if user cannot get gems gems', async () => {
|
it('should error if user cannot get gems gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
await expect(amzLib.checkout({user, orderReferenceId, headers})).to.eventually.be.rejected.and.to.eql({
|
await expect(amzLib.checkout({user, orderReferenceId, headers})).to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
message: i18n.t('groupPolicyCannotGetGems'),
|
message: i18n.t('groupPolicyCannotGetGems'),
|
||||||
|
|||||||
@@ -46,16 +46,16 @@ describe('Amazon Payments - Subscribe', () => {
|
|||||||
headers = {};
|
headers = {};
|
||||||
|
|
||||||
amazonSetBillingAgreementDetailsSpy = sinon.stub(amzLib, 'setBillingAgreementDetails');
|
amazonSetBillingAgreementDetailsSpy = sinon.stub(amzLib, 'setBillingAgreementDetails');
|
||||||
amazonSetBillingAgreementDetailsSpy.returnsPromise().resolves({});
|
amazonSetBillingAgreementDetailsSpy.resolves({});
|
||||||
|
|
||||||
amazonConfirmBillingAgreementSpy = sinon.stub(amzLib, 'confirmBillingAgreement');
|
amazonConfirmBillingAgreementSpy = sinon.stub(amzLib, 'confirmBillingAgreement');
|
||||||
amazonConfirmBillingAgreementSpy.returnsPromise().resolves({});
|
amazonConfirmBillingAgreementSpy.resolves({});
|
||||||
|
|
||||||
amazonAuthorizeOnBillingAgreementSpy = sinon.stub(amzLib, 'authorizeOnBillingAgreement');
|
amazonAuthorizeOnBillingAgreementSpy = sinon.stub(amzLib, 'authorizeOnBillingAgreement');
|
||||||
amazonAuthorizeOnBillingAgreementSpy.returnsPromise().resolves({});
|
amazonAuthorizeOnBillingAgreementSpy.resolves({});
|
||||||
|
|
||||||
createSubSpy = sinon.stub(payments, 'createSubscription');
|
createSubSpy = sinon.stub(payments, 'createSubscription');
|
||||||
createSubSpy.returnsPromise().resolves({});
|
createSubSpy.resolves({});
|
||||||
|
|
||||||
sinon.stub(common, 'uuid').returns('uuid-generated');
|
sinon.stub(common, 'uuid').returns('uuid-generated');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ describe('#upgradeGroupPlan', () => {
|
|||||||
await group.save();
|
await group.save();
|
||||||
|
|
||||||
spy = sinon.stub(amzLib, 'authorizeOnBillingAgreement');
|
spy = sinon.stub(amzLib, 'authorizeOnBillingAgreement');
|
||||||
spy.returnsPromise().resolves([]);
|
spy.resolves([]);
|
||||||
|
|
||||||
uuidString = 'uuid-v4';
|
uuidString = 'uuid-v4';
|
||||||
sinon.stub(uuid, 'v4').returns(uuidString);
|
sinon.stub(uuid, 'v4').returns(uuidString);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import iap from '../../../../../website/server/libs/inAppPurchases';
|
|||||||
import {model as User} from '../../../../../website/server/models/user';
|
import {model as User} from '../../../../../website/server/models/user';
|
||||||
import common from '../../../../../website/common';
|
import common from '../../../../../website/common';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import {mockFindById, restoreFindById} from '../../../../helpers/mongoose.helper';
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const i18n = common.i18n;
|
||||||
|
|
||||||
@@ -24,16 +25,16 @@ describe('Apple Payments', () => {
|
|||||||
headers = {};
|
headers = {};
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iapModule, 'setup')
|
||||||
.returnsPromise().resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iapModule, 'validate')
|
||||||
.returnsPromise().resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
||||||
.returns([{productId: 'com.habitrpg.ios.Habitica.21gems',
|
.returns([{productId: 'com.habitrpg.ios.Habitica.21gems',
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').returnsPromise().resolves({});
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -49,7 +50,7 @@ describe('Apple Payments', () => {
|
|||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(applePayments.verifyGemPurchase(user, receipt, headers))
|
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -61,7 +62,7 @@ describe('Apple Payments', () => {
|
|||||||
iapGetPurchaseDataStub.restore();
|
iapGetPurchaseDataStub.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData').returns([]);
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData').returns([]);
|
||||||
|
|
||||||
await expect(applePayments.verifyGemPurchase(user, receipt, headers))
|
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -70,8 +71,8 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('errors if the user cannot purchase gems', async () => {
|
it('errors if the user cannot purchase gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
await expect(applePayments.verifyGemPurchase(user, receipt, headers))
|
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -82,14 +83,14 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('errors if amount does not exist', async () => {
|
it('errors if amount does not exist', async () => {
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
iapGetPurchaseDataStub.restore();
|
iapGetPurchaseDataStub.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
||||||
.returns([{productId: 'badProduct',
|
.returns([{productId: 'badProduct',
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
await expect(applePayments.verifyGemPurchase(user, receipt, headers))
|
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -130,8 +131,8 @@ describe('Apple Payments', () => {
|
|||||||
transactionId: token,
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
await applePayments.verifyGemPurchase(user, receipt, headers);
|
await applePayments.verifyGemPurchase({user, receipt, headers});
|
||||||
|
|
||||||
expect(iapSetupStub).to.be.calledOnce;
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
expect(iapValidateStub).to.be.calledOnce;
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
@@ -151,6 +152,38 @@ describe('Apple Payments', () => {
|
|||||||
user.canGetGems.restore();
|
user.canGetGems.restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('gifts gems', async () => {
|
||||||
|
const receivingUser = new User();
|
||||||
|
await receivingUser.save();
|
||||||
|
|
||||||
|
mockFindById(receivingUser);
|
||||||
|
|
||||||
|
iapGetPurchaseDataStub.restore();
|
||||||
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
||||||
|
.returns([{productId: gemsCanPurchase[0].productId,
|
||||||
|
transactionId: token,
|
||||||
|
}]);
|
||||||
|
|
||||||
|
const gift = {uuid: receivingUser._id};
|
||||||
|
await applePayments.verifyGemPurchase({user, gift, receipt, headers});
|
||||||
|
|
||||||
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
|
expect(iapValidateStub).to.be.calledWith(iap.APPLE, receipt);
|
||||||
|
expect(iapIsValidatedStub).to.be.calledOnce;
|
||||||
|
expect(iapIsValidatedStub).to.be.calledWith({});
|
||||||
|
expect(iapGetPurchaseDataStub).to.be.calledOnce;
|
||||||
|
|
||||||
|
expect(paymentBuyGemsStub).to.be.calledOnce;
|
||||||
|
expect(paymentBuyGemsStub).to.be.calledWith({
|
||||||
|
user: receivingUser,
|
||||||
|
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
|
||||||
|
amount: gemsCanPurchase[0].amount,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
restoreFindById();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('subscribe', () => {
|
describe('subscribe', () => {
|
||||||
@@ -167,9 +200,9 @@ describe('Apple Payments', () => {
|
|||||||
nextPaymentProcessing = moment.utc().add({days: 2});
|
nextPaymentProcessing = moment.utc().add({days: 2});
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iapModule, 'setup')
|
||||||
.returnsPromise().resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iapModule, 'validate')
|
||||||
.returnsPromise().resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
||||||
@@ -186,7 +219,7 @@ describe('Apple Payments', () => {
|
|||||||
productId: sku,
|
productId: sku,
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').returnsPromise().resolves({});
|
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -297,9 +330,9 @@ describe('Apple Payments', () => {
|
|||||||
expirationDate = moment.utc();
|
expirationDate = moment.utc();
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iapModule, 'setup')
|
||||||
.returnsPromise().resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iapModule, 'validate')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
expirationDate,
|
expirationDate,
|
||||||
});
|
});
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
||||||
@@ -314,7 +347,7 @@ describe('Apple Payments', () => {
|
|||||||
user.purchased.plan.planId = subKey;
|
user.purchased.plan.planId = subKey;
|
||||||
user.purchased.plan.additionalData = receipt;
|
user.purchased.plan.additionalData = receipt;
|
||||||
|
|
||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').returnsPromise().resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import iap from '../../../../../website/server/libs/inAppPurchases';
|
|||||||
import {model as User} from '../../../../../website/server/models/user';
|
import {model as User} from '../../../../../website/server/models/user';
|
||||||
import common from '../../../../../website/common';
|
import common from '../../../../../website/common';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import {mockFindById, restoreFindById} from '../../../../helpers/mongoose.helper';
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const i18n = common.i18n;
|
||||||
|
|
||||||
@@ -24,12 +25,12 @@ describe('Google Payments', () => {
|
|||||||
headers = {};
|
headers = {};
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iapModule, 'setup')
|
||||||
.returnsPromise().resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iapModule, 'validate')
|
||||||
.returnsPromise().resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').returnsPromise().resolves({});
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -44,7 +45,7 @@ describe('Google Payments', () => {
|
|||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(googlePayments.verifyGemPurchase(user, receipt, signature, headers))
|
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -55,7 +56,7 @@ describe('Google Payments', () => {
|
|||||||
it('should throw an error if productId is invalid', async () => {
|
it('should throw an error if productId is invalid', async () => {
|
||||||
receipt = `{"token": "${token}", "productId": "invalid"}`;
|
receipt = `{"token": "${token}", "productId": "invalid"}`;
|
||||||
|
|
||||||
await expect(googlePayments.verifyGemPurchase(user, receipt, signature, headers))
|
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -64,9 +65,9 @@ describe('Google Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if user cannot purchase gems', async () => {
|
it('should throw an error if user cannot purchase gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
|
|
||||||
await expect(googlePayments.verifyGemPurchase(user, receipt, signature, headers))
|
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -77,8 +78,8 @@ describe('Google Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('purchases gems', async () => {
|
it('purchases gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
await googlePayments.verifyGemPurchase(user, receipt, signature, headers);
|
await googlePayments.verifyGemPurchase({user, receipt, signature, headers});
|
||||||
|
|
||||||
expect(iapSetupStub).to.be.calledOnce;
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
expect(iapValidateStub).to.be.calledOnce;
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
@@ -99,6 +100,34 @@ describe('Google Payments', () => {
|
|||||||
expect(user.canGetGems).to.be.calledOnce;
|
expect(user.canGetGems).to.be.calledOnce;
|
||||||
user.canGetGems.restore();
|
user.canGetGems.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('gifts gems', async () => {
|
||||||
|
const receivingUser = new User();
|
||||||
|
await receivingUser.save();
|
||||||
|
|
||||||
|
mockFindById(receivingUser);
|
||||||
|
|
||||||
|
const gift = {uuid: receivingUser._id};
|
||||||
|
await googlePayments.verifyGemPurchase({user, gift, receipt, signature, headers});
|
||||||
|
|
||||||
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
|
expect(iapValidateStub).to.be.calledWith(iap.GOOGLE, {
|
||||||
|
data: receipt,
|
||||||
|
signature,
|
||||||
|
});
|
||||||
|
expect(iapIsValidatedStub).to.be.calledOnce;
|
||||||
|
expect(iapIsValidatedStub).to.be.calledWith({});
|
||||||
|
|
||||||
|
expect(paymentBuyGemsStub).to.be.calledOnce;
|
||||||
|
expect(paymentBuyGemsStub).to.be.calledWith({
|
||||||
|
user: receivingUser,
|
||||||
|
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
|
||||||
|
amount: 5.25,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
restoreFindById();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('subscribe', () => {
|
describe('subscribe', () => {
|
||||||
@@ -116,12 +145,12 @@ describe('Google Payments', () => {
|
|||||||
nextPaymentProcessing = moment.utc().add({days: 2});
|
nextPaymentProcessing = moment.utc().add({days: 2});
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iapModule, 'setup')
|
||||||
.returnsPromise().resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iapModule, 'validate')
|
||||||
.returnsPromise().resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').returnsPromise().resolves({});
|
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -193,9 +222,9 @@ describe('Google Payments', () => {
|
|||||||
expirationDate = moment.utc();
|
expirationDate = moment.utc();
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iapModule, 'setup')
|
||||||
.returnsPromise().resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iapModule, 'validate')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
expirationDate,
|
expirationDate,
|
||||||
});
|
});
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
||||||
@@ -210,7 +239,7 @@ describe('Google Payments', () => {
|
|||||||
user.purchased.plan.planId = subKey;
|
user.purchased.plan.planId = subKey;
|
||||||
user.purchased.plan.additionalData = {data: receipt, signature};
|
user.purchased.plan.additionalData = {data: receipt, signature};
|
||||||
|
|
||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').returnsPromise().resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
|||||||
@@ -69,11 +69,11 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let subscriptionId = 'subId';
|
let subscriptionId = 'subId';
|
||||||
sinon.stub(stripe.customers, 'del').returnsPromise().resolves({});
|
sinon.stub(stripe.customers, 'del').resolves({});
|
||||||
|
|
||||||
let currentPeriodEndTimeStamp = moment().add(3, 'months').unix();
|
let currentPeriodEndTimeStamp = moment().add(3, 'months').unix();
|
||||||
sinon.stub(stripe.customers, 'retrieve')
|
sinon.stub(stripe.customers, 'retrieve')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
subscriptions: {
|
subscriptions: {
|
||||||
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
|
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
|
||||||
},
|
},
|
||||||
@@ -216,7 +216,6 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
it('sends one email to subscribed member of group, stating subscription is cancelled (Amazon)', async () => {
|
it('sends one email to subscribed member of group, stating subscription is cancelled (Amazon)', async () => {
|
||||||
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
||||||
.returnsPromise()
|
|
||||||
.resolves({
|
.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Closed'},
|
BillingAgreementStatus: {State: 'Closed'},
|
||||||
@@ -251,9 +250,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sends one email to subscribed member of group, stating subscription is cancelled (PayPal)', async () => {
|
it('sends one email to subscribed member of group, stating subscription is cancelled (PayPal)', async () => {
|
||||||
sinon.stub(paypalPayments, 'paypalBillingAgreementCancel').returnsPromise().resolves({});
|
sinon.stub(paypalPayments, 'paypalBillingAgreementCancel').resolves({});
|
||||||
sinon.stub(paypalPayments, 'paypalBillingAgreementGet')
|
sinon.stub(paypalPayments, 'paypalBillingAgreementGet')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
agreement_details: { // eslint-disable-line camelcase
|
agreement_details: { // eslint-disable-line camelcase
|
||||||
next_billing_date: moment().add(3, 'months').toDate(), // eslint-disable-line camelcase
|
next_billing_date: moment().add(3, 'months').toDate(), // eslint-disable-line camelcase
|
||||||
cycles_completed: 1, // eslint-disable-line camelcase
|
cycles_completed: 1, // eslint-disable-line camelcase
|
||||||
@@ -449,7 +448,6 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
it('adds months to members with existing recurring subscription (Amazon)', async () => {
|
it('adds months to members with existing recurring subscription (Amazon)', async () => {
|
||||||
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
||||||
.returnsPromise()
|
|
||||||
.resolves({
|
.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Closed'},
|
BillingAgreementStatus: {State: 'Closed'},
|
||||||
@@ -478,9 +476,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members with existing recurring subscription (Paypal)', async () => {
|
it('adds months to members with existing recurring subscription (Paypal)', async () => {
|
||||||
sinon.stub(paypalPayments, 'paypalBillingAgreementCancel').returnsPromise().resolves({});
|
sinon.stub(paypalPayments, 'paypalBillingAgreementCancel').resolves({});
|
||||||
sinon.stub(paypalPayments, 'paypalBillingAgreementGet')
|
sinon.stub(paypalPayments, 'paypalBillingAgreementGet')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
agreement_details: { // eslint-disable-line camelcase
|
agreement_details: { // eslint-disable-line camelcase
|
||||||
next_billing_date: moment().add(3, 'months').toDate(), // eslint-disable-line camelcase
|
next_billing_date: moment().add(3, 'months').toDate(), // eslint-disable-line camelcase
|
||||||
cycles_completed: 1, // eslint-disable-line camelcase
|
cycles_completed: 1, // eslint-disable-line camelcase
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ describe('checkout success', () => {
|
|||||||
customerId = 'customerId-test';
|
customerId = 'customerId-test';
|
||||||
paymentId = 'paymentId-test';
|
paymentId = 'paymentId-test';
|
||||||
|
|
||||||
paypalPaymentExecuteStub = sinon.stub(paypalPayments, 'paypalPaymentExecute').returnsPromise().resolves({});
|
paypalPaymentExecuteStub = sinon.stub(paypalPayments, 'paypalPaymentExecute').resolves({});
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').returnsPromise().resolves({});
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
||||||
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').returnsPromise().resolves({});
|
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ describe('checkout', () => {
|
|||||||
|
|
||||||
function getPaypalCreateOptions (description, amount) {
|
function getPaypalCreateOptions (description, amount) {
|
||||||
return {
|
return {
|
||||||
|
experience_profile_id: 'xp_profile_id',
|
||||||
intent: 'sale',
|
intent: 'sale',
|
||||||
payer: { payment_method: 'Paypal' },
|
payer: { payment_method: 'Paypal' },
|
||||||
redirect_urls: {
|
redirect_urls: {
|
||||||
@@ -42,7 +43,7 @@ describe('checkout', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
approvalHerf = 'approval_href';
|
approvalHerf = 'approval_href';
|
||||||
paypalPaymentCreateStub = sinon.stub(paypalPayments, 'paypalPaymentCreate')
|
paypalPaymentCreateStub = sinon.stub(paypalPayments, 'paypalPaymentCreate')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
links: [{ rel: 'approval_url', href: approvalHerf }],
|
links: [{ rel: 'approval_url', href: approvalHerf }],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -80,7 +81,7 @@ describe('checkout', () => {
|
|||||||
|
|
||||||
it('should error if the user cannot get gems', async () => {
|
it('should error if the user cannot get gems', async () => {
|
||||||
let user = new User();
|
let user = new User();
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
|
|
||||||
await expect(paypalPayments.checkout({user})).to.eventually.be.rejected.and.to.eql({
|
await expect(paypalPayments.checkout({user})).to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ describe('ipn', () => {
|
|||||||
group.purchased.plan.lastBillingDate = new Date();
|
group.purchased.plan.lastBillingDate = new Date();
|
||||||
await group.save();
|
await group.save();
|
||||||
|
|
||||||
ipnVerifyAsyncStub = sinon.stub(paypalPayments, 'ipnVerifyAsync').returnsPromise().resolves({});
|
ipnVerifyAsyncStub = sinon.stub(paypalPayments, 'ipnVerifyAsync').resolves({});
|
||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').returnsPromise().resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
|||||||
@@ -38,15 +38,15 @@ describe('subscribeCancel', () => {
|
|||||||
|
|
||||||
nextBillingDate = new Date();
|
nextBillingDate = new Date();
|
||||||
|
|
||||||
paypalBillingAgreementCancelStub = sinon.stub(paypalPayments, 'paypalBillingAgreementCancel').returnsPromise().resolves({});
|
paypalBillingAgreementCancelStub = sinon.stub(paypalPayments, 'paypalBillingAgreementCancel').resolves({});
|
||||||
paypalBillingAgreementGetStub = sinon.stub(paypalPayments, 'paypalBillingAgreementGet')
|
paypalBillingAgreementGetStub = sinon.stub(paypalPayments, 'paypalBillingAgreementGet')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
agreement_details: {
|
agreement_details: {
|
||||||
next_billing_date: nextBillingDate,
|
next_billing_date: nextBillingDate,
|
||||||
cycles_completed: 1,
|
cycles_completed: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').returnsPromise().resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ describe('subscribeSuccess', () => {
|
|||||||
customerId = 'test-customerId';
|
customerId = 'test-customerId';
|
||||||
|
|
||||||
paypalBillingAgreementExecuteStub = sinon.stub(paypalPayments, 'paypalBillingAgreementExecute')
|
paypalBillingAgreementExecuteStub = sinon.stub(paypalPayments, 'paypalBillingAgreementExecute')
|
||||||
.returnsPromise({}).resolves({
|
.resolves({
|
||||||
id: customerId,
|
id: customerId,
|
||||||
});
|
});
|
||||||
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').returnsPromise().resolves({});
|
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('subscribe', () => {
|
|||||||
sub = Object.assign({}, common.content.subscriptionBlocks[subKey]);
|
sub = Object.assign({}, common.content.subscriptionBlocks[subKey]);
|
||||||
|
|
||||||
paypalBillingAgreementCreateStub = sinon.stub(paypalPayments, 'paypalBillingAgreementCreate')
|
paypalBillingAgreementCreateStub = sinon.stub(paypalPayments, 'paypalBillingAgreementCreate')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
links: [{ rel: 'approval_url', href: approvalHerf }],
|
links: [{ rel: 'approval_url', href: approvalHerf }],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -82,12 +82,12 @@ describe('cancel subscription', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
subscriptionId = 'subId';
|
subscriptionId = 'subId';
|
||||||
stripeDeleteCustomerStub = sinon.stub(stripe.customers, 'del').returnsPromise().resolves({});
|
stripeDeleteCustomerStub = sinon.stub(stripe.customers, 'del').resolves({});
|
||||||
paymentsCancelSubStub = sinon.stub(payments, 'cancelSubscription').returnsPromise().resolves({});
|
paymentsCancelSubStub = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
|
|
||||||
currentPeriodEndTimeStamp = (new Date()).getTime();
|
currentPeriodEndTimeStamp = (new Date()).getTime();
|
||||||
stripeRetrieveStub = sinon.stub(stripe.customers, 'retrieve')
|
stripeRetrieveStub = sinon.stub(stripe.customers, 'retrieve')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
subscriptions: {
|
subscriptions: {
|
||||||
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
|
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ describe('checkout with subscription', () => {
|
|||||||
token = 'test-token';
|
token = 'test-token';
|
||||||
|
|
||||||
spy = sinon.stub(stripe.subscriptions, 'update');
|
spy = sinon.stub(stripe.subscriptions, 'update');
|
||||||
spy.returnsPromise().resolves;
|
spy.resolves;
|
||||||
|
|
||||||
stripeCreateCustomerSpy = sinon.stub(stripe.customers, 'create');
|
stripeCreateCustomerSpy = sinon.stub(stripe.customers, 'create');
|
||||||
let stripCustomerResponse = {
|
let stripCustomerResponse = {
|
||||||
@@ -63,10 +63,10 @@ describe('checkout with subscription', () => {
|
|||||||
data: [{id: subscriptionId}],
|
data: [{id: subscriptionId}],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
stripeCreateCustomerSpy.returnsPromise().resolves(stripCustomerResponse);
|
stripeCreateCustomerSpy.resolves(stripCustomerResponse);
|
||||||
|
|
||||||
stripePaymentsCreateSubSpy = sinon.stub(payments, 'createSubscription');
|
stripePaymentsCreateSubSpy = sinon.stub(payments, 'createSubscription');
|
||||||
stripePaymentsCreateSubSpy.returnsPromise().resolves({});
|
stripePaymentsCreateSubSpy.resolves({});
|
||||||
|
|
||||||
data.groupId = group._id;
|
data.groupId = group._id;
|
||||||
data.sub.quantity = 3;
|
data.sub.quantity = 3;
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ describe('checkout', () => {
|
|||||||
let stripCustomerResponse = {
|
let stripCustomerResponse = {
|
||||||
id: customerIdResponse,
|
id: customerIdResponse,
|
||||||
};
|
};
|
||||||
stripeChargeStub = sinon.stub(stripe.charges, 'create').returnsPromise().resolves(stripCustomerResponse);
|
stripeChargeStub = sinon.stub(stripe.charges, 'create').resolves(stripCustomerResponse);
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').returnsPromise().resolves({});
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
||||||
paymentCreateSubscritionStub = sinon.stub(payments, 'createSubscription').returnsPromise().resolves({});
|
paymentCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -82,7 +82,7 @@ describe('checkout', () => {
|
|||||||
|
|
||||||
it('should error if user cannot get gems', async () => {
|
it('should error if user cannot get gems', async () => {
|
||||||
gift = undefined;
|
gift = undefined;
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
|
|
||||||
await expect(stripePayments.checkout({
|
await expect(stripePayments.checkout({
|
||||||
token,
|
token,
|
||||||
@@ -101,7 +101,7 @@ describe('checkout', () => {
|
|||||||
|
|
||||||
it('should purchase gems', async () => {
|
it('should purchase gems', async () => {
|
||||||
gift = undefined;
|
gift = undefined;
|
||||||
sinon.stub(user, 'canGetGems').returnsPromise().resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
|
|
||||||
await stripePayments.checkout({
|
await stripePayments.checkout({
|
||||||
token,
|
token,
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ describe('edit subscription', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
subscriptionId = 'subId';
|
subscriptionId = 'subId';
|
||||||
stripeListSubscriptionStub = sinon.stub(stripe.customers, 'listSubscriptions')
|
stripeListSubscriptionStub = sinon.stub(stripe.customers, 'listSubscriptions')
|
||||||
.returnsPromise().resolves({
|
.resolves({
|
||||||
data: [{id: subscriptionId}],
|
data: [{id: subscriptionId}],
|
||||||
});
|
});
|
||||||
|
|
||||||
stripeUpdateSubscriptionStub = sinon.stub(stripe.customers, 'updateSubscription').returnsPromise().resolves({});
|
stripeUpdateSubscriptionStub = sinon.stub(stripe.customers, 'updateSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
const eventRetrieved = {type: eventType};
|
const eventRetrieved = {type: eventType};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves(eventRetrieved);
|
sinon.stub(stripe.events, 'retrieve').resolves(eventRetrieved);
|
||||||
sinon.stub(logger, 'error');
|
sinon.stub(logger, 'error');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -52,8 +52,8 @@ describe('Stripe - Webhooks', () => {
|
|||||||
const eventType = 'customer.subscription.deleted';
|
const eventType = 'customer.subscription.deleted';
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sinon.stub(stripe.customers, 'del').returnsPromise().resolves({});
|
sinon.stub(stripe.customers, 'del').resolves({});
|
||||||
sinon.stub(payments, 'cancelSubscription').returnsPromise().resolves({});
|
sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -62,7 +62,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not do anything if event.request is null (subscription cancelled manually)', async () => {
|
it('does not do anything if event.request is null (subscription cancelled manually)', async () => {
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves({
|
sinon.stub(stripe.events, 'retrieve').resolves({
|
||||||
id: 123,
|
id: 123,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
request: 123,
|
request: 123,
|
||||||
@@ -79,7 +79,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
describe('user subscription', () => {
|
describe('user subscription', () => {
|
||||||
it('throws an error if the user is not found', async () => {
|
it('throws an error if the user is not found', async () => {
|
||||||
const customerId = 456;
|
const customerId = 456;
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves({
|
sinon.stub(stripe.events, 'retrieve').resolves({
|
||||||
id: 123,
|
id: 123,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
data: {
|
data: {
|
||||||
@@ -113,7 +113,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
subscriber.purchased.plan.paymentMethod = 'Stripe';
|
subscriber.purchased.plan.paymentMethod = 'Stripe';
|
||||||
await subscriber.save();
|
await subscriber.save();
|
||||||
|
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves({
|
sinon.stub(stripe.events, 'retrieve').resolves({
|
||||||
id: 123,
|
id: 123,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
data: {
|
data: {
|
||||||
@@ -146,7 +146,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
describe('group plan subscription', () => {
|
describe('group plan subscription', () => {
|
||||||
it('throws an error if the group is not found', async () => {
|
it('throws an error if the group is not found', async () => {
|
||||||
const customerId = 456;
|
const customerId = 456;
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves({
|
sinon.stub(stripe.events, 'retrieve').resolves({
|
||||||
id: 123,
|
id: 123,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
data: {
|
data: {
|
||||||
@@ -185,7 +185,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
subscriber.purchased.plan.paymentMethod = 'Stripe';
|
subscriber.purchased.plan.paymentMethod = 'Stripe';
|
||||||
await subscriber.save();
|
await subscriber.save();
|
||||||
|
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves({
|
sinon.stub(stripe.events, 'retrieve').resolves({
|
||||||
id: 123,
|
id: 123,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
data: {
|
data: {
|
||||||
@@ -227,7 +227,7 @@ describe('Stripe - Webhooks', () => {
|
|||||||
subscriber.purchased.plan.paymentMethod = 'Stripe';
|
subscriber.purchased.plan.paymentMethod = 'Stripe';
|
||||||
await subscriber.save();
|
await subscriber.save();
|
||||||
|
|
||||||
sinon.stub(stripe.events, 'retrieve').returnsPromise().resolves({
|
sinon.stub(stripe.events, 'retrieve').resolves({
|
||||||
id: 123,
|
id: 123,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ describe('Stripe - Upgrade Group Plan', () => {
|
|||||||
await group.save();
|
await group.save();
|
||||||
|
|
||||||
spy = sinon.stub(stripe.subscriptions, 'update');
|
spy = sinon.stub(stripe.subscriptions, 'update');
|
||||||
spy.returnsPromise().resolves([]);
|
spy.resolves([]);
|
||||||
data.groupId = group._id;
|
data.groupId = group._id;
|
||||||
data.sub.quantity = 3;
|
data.sub.quantity = 3;
|
||||||
stripePayments.setStripeApi(stripe);
|
stripePayments.setStripeApi(stripe);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ describe('slack', () => {
|
|||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
id: 'chat-id',
|
id: 'chat-id',
|
||||||
|
username: 'author',
|
||||||
user: 'Author',
|
user: 'Author',
|
||||||
uuid: 'author-id',
|
uuid: 'author-id',
|
||||||
text: 'some text',
|
text: 'some text',
|
||||||
@@ -50,11 +51,11 @@ describe('slack', () => {
|
|||||||
|
|
||||||
expect(IncomingWebhook.prototype.send).to.be.calledOnce;
|
expect(IncomingWebhook.prototype.send).to.be.calledOnce;
|
||||||
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
||||||
text: 'flagger (flagger-id; language: flagger-lang) flagged a message',
|
text: 'flagger (flagger-id; language: flagger-lang) flagged a group message',
|
||||||
attachments: [{
|
attachments: [{
|
||||||
fallback: 'Flag Message',
|
fallback: 'Flag Message',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
author_name: `Author - author@example.com - author-id\n${timestamp}`,
|
author_name: `@author Author (author@example.com; author-id)\n${timestamp}`,
|
||||||
title: 'Flag in Some group - (private guild)',
|
title: 'Flag in Some group - (private guild)',
|
||||||
title_link: undefined,
|
title_link: undefined,
|
||||||
text: 'some text',
|
text: 'some text',
|
||||||
@@ -110,7 +111,7 @@ describe('slack', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('noops if no flagging url is provided', () => {
|
it('noops if no flagging url is provided', () => {
|
||||||
sandbox.stub(nconf, 'get').withArgs('SLACK:FLAGGING_URL').returns('');
|
sandbox.stub(nconf, 'get').withArgs('SLACK_FLAGGING_URL').returns('');
|
||||||
sandbox.stub(logger, 'error');
|
sandbox.stub(logger, 'error');
|
||||||
let reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
|
let reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,56 @@ describe('redirects middleware', () => {
|
|||||||
|
|
||||||
expect(res.redirect).to.have.not.been.called;
|
expect(res.redirect).to.have.not.been.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not redirect if passed skip ssl request param is passed with corrrect key', () => {
|
||||||
|
let nconfStub = sandbox.stub(nconf, 'get');
|
||||||
|
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
|
||||||
|
nconfStub.withArgs('IS_PROD').returns(true);
|
||||||
|
nconfStub.withArgs('SKIP_SSL_CHECK_KEY').returns('test-key');
|
||||||
|
|
||||||
|
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('http');
|
||||||
|
req.originalUrl = '/static/front';
|
||||||
|
req.query.skipSSLCheck = 'test-key';
|
||||||
|
|
||||||
|
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
|
||||||
|
attachRedirects.forceSSL(req, res, next);
|
||||||
|
|
||||||
|
expect(res.redirect).to.have.not.been.called;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does redirect if skip ssl request param is passed with incorrrect key', () => {
|
||||||
|
let nconfStub = sandbox.stub(nconf, 'get');
|
||||||
|
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
|
||||||
|
nconfStub.withArgs('IS_PROD').returns(true);
|
||||||
|
nconfStub.withArgs('SKIP_SSL_CHECK_KEY').returns('test-key');
|
||||||
|
|
||||||
|
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('http');
|
||||||
|
req.originalUrl = '/static/front?skipSSLCheck=INVALID';
|
||||||
|
req.query.skipSSLCheck = 'INVALID';
|
||||||
|
|
||||||
|
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
|
||||||
|
attachRedirects.forceSSL(req, res, next);
|
||||||
|
|
||||||
|
expect(res.redirect).to.be.calledOnce;
|
||||||
|
expect(res.redirect).to.be.calledWith('https://habitica.com/static/front?skipSSLCheck=INVALID');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does redirect if skip ssl check key is not set', () => {
|
||||||
|
let nconfStub = sandbox.stub(nconf, 'get');
|
||||||
|
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
|
||||||
|
nconfStub.withArgs('IS_PROD').returns(true);
|
||||||
|
nconfStub.withArgs('SKIP_SSL_CHECK_KEY').returns(null);
|
||||||
|
|
||||||
|
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('http');
|
||||||
|
req.originalUrl = '/static/front';
|
||||||
|
req.query.skipSSLCheck = 'INVALID';
|
||||||
|
|
||||||
|
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
|
||||||
|
attachRedirects.forceSSL(req, res, next);
|
||||||
|
|
||||||
|
expect(res.redirect).to.be.calledOnce;
|
||||||
|
expect(res.redirect).to.be.calledWith('https://habitica.com/static/front');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context('forceHabitica', () => {
|
context('forceHabitica', () => {
|
||||||
|
|||||||
@@ -32,8 +32,19 @@ describe('Group Model', () => {
|
|||||||
privacy: 'private',
|
privacy: 'private',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let _progress = {
|
||||||
|
up: 10,
|
||||||
|
down: 8,
|
||||||
|
collectedItems: 5,
|
||||||
|
};
|
||||||
|
|
||||||
questLeader = new User({
|
questLeader = new User({
|
||||||
party: { _id: party._id },
|
party: {
|
||||||
|
_id: party._id,
|
||||||
|
quest: {
|
||||||
|
progress: _progress,
|
||||||
|
},
|
||||||
|
},
|
||||||
profile: { name: 'Quest Leader' },
|
profile: { name: 'Quest Leader' },
|
||||||
items: {
|
items: {
|
||||||
quests: {
|
quests: {
|
||||||
@@ -45,20 +56,40 @@ describe('Group Model', () => {
|
|||||||
party.leader = questLeader._id;
|
party.leader = questLeader._id;
|
||||||
|
|
||||||
participatingMember = new User({
|
participatingMember = new User({
|
||||||
party: { _id: party._id },
|
party: {
|
||||||
|
_id: party._id,
|
||||||
|
quest: {
|
||||||
|
progress: _progress,
|
||||||
|
},
|
||||||
|
},
|
||||||
profile: { name: 'Participating Member' },
|
profile: { name: 'Participating Member' },
|
||||||
});
|
});
|
||||||
sleepingParticipatingMember = new User({
|
sleepingParticipatingMember = new User({
|
||||||
party: { _id: party._id },
|
party: {
|
||||||
|
_id: party._id,
|
||||||
|
quest: {
|
||||||
|
progress: _progress,
|
||||||
|
},
|
||||||
|
},
|
||||||
profile: { name: 'Sleeping Participating Member' },
|
profile: { name: 'Sleeping Participating Member' },
|
||||||
preferences: { sleep: true },
|
preferences: { sleep: true },
|
||||||
});
|
});
|
||||||
nonParticipatingMember = new User({
|
nonParticipatingMember = new User({
|
||||||
party: { _id: party._id },
|
party: {
|
||||||
|
_id: party._id,
|
||||||
|
quest: {
|
||||||
|
progress: _progress,
|
||||||
|
},
|
||||||
|
},
|
||||||
profile: { name: 'Non-Participating Member' },
|
profile: { name: 'Non-Participating Member' },
|
||||||
});
|
});
|
||||||
undecidedMember = new User({
|
undecidedMember = new User({
|
||||||
party: { _id: party._id },
|
party: {
|
||||||
|
_id: party._id,
|
||||||
|
quest: {
|
||||||
|
progress: _progress,
|
||||||
|
},
|
||||||
|
},
|
||||||
profile: { name: 'Undecided Member' },
|
profile: { name: 'Undecided Member' },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -477,7 +508,7 @@ describe('Group Model', () => {
|
|||||||
party.quest.active = false;
|
party.quest.active = false;
|
||||||
|
|
||||||
await party.startQuest(questLeader);
|
await party.startQuest(questLeader);
|
||||||
Group.prototype.sendChat.reset();
|
Group.prototype.sendChat.resetHistory();
|
||||||
await party.save();
|
await party.save();
|
||||||
|
|
||||||
await Group.processQuestProgress(participatingMember, progress);
|
await Group.processQuestProgress(participatingMember, progress);
|
||||||
@@ -496,7 +527,7 @@ describe('Group Model', () => {
|
|||||||
party.quest.active = false;
|
party.quest.active = false;
|
||||||
|
|
||||||
await party.startQuest(questLeader);
|
await party.startQuest(questLeader);
|
||||||
Group.prototype.sendChat.reset();
|
Group.prototype.sendChat.resetHistory();
|
||||||
await party.save();
|
await party.save();
|
||||||
|
|
||||||
await Group.processQuestProgress(participatingMember, progress);
|
await Group.processQuestProgress(participatingMember, progress);
|
||||||
@@ -569,7 +600,7 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if no uuids or emails are passed in', async () => {
|
it('throws an error if no uuids or emails are passed in', async () => {
|
||||||
await expect(Group.validateInvitations(null, null, res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
@@ -579,7 +610,7 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if only uuids are passed in, but they are not an array', async () => {
|
it('throws an error if only uuids are passed in, but they are not an array', async () => {
|
||||||
await expect(Group.validateInvitations({ uuid: 'user-id'}, null, res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({ uuids: 'user-id'}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
@@ -589,7 +620,7 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if only emails are passed in, but they are not an array', async () => {
|
it('throws an error if only emails are passed in, but they are not an array', async () => {
|
||||||
await expect(Group.validateInvitations(null, { emails: 'user@example.com'}, res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({emails: 'user@example.com'}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
@@ -599,27 +630,27 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if emails are not passed in, and uuid array is empty', async () => {
|
it('throws an error if emails are not passed in, and uuid array is empty', async () => {
|
||||||
await expect(Group.validateInvitations([], null, res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({uuids: []}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
});
|
});
|
||||||
expect(res.t).to.be.calledOnce;
|
expect(res.t).to.be.calledOnce;
|
||||||
expect(res.t).to.be.calledWith('inviteMissingUuid');
|
expect(res.t).to.be.calledWith('inviteMustNotBeEmpty');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if uuids are not passed in, and email array is empty', async () => {
|
it('throws an error if uuids are not passed in, and email array is empty', async () => {
|
||||||
await expect(Group.validateInvitations(null, [], res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({emails: []}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
});
|
});
|
||||||
expect(res.t).to.be.calledOnce;
|
expect(res.t).to.be.calledOnce;
|
||||||
expect(res.t).to.be.calledWith('inviteMissingEmail');
|
expect(res.t).to.be.calledWith('inviteMustNotBeEmpty');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if uuids and emails are passed in as empty arrays', async () => {
|
it('throws an error if uuids and emails are passed in as empty arrays', async () => {
|
||||||
await expect(Group.validateInvitations([], [], res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({emails: [], uuids: []}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
@@ -639,7 +670,7 @@ describe('Group Model', () => {
|
|||||||
|
|
||||||
uuids.push('one-more-uuid'); // to put it over the limit
|
uuids.push('one-more-uuid'); // to put it over the limit
|
||||||
|
|
||||||
await expect(Group.validateInvitations(uuids, emails, res)).to.eventually.be.rejected.and.eql({
|
await expect(Group.validateInvitations({uuids, emails}, res)).to.eventually.be.rejected.and.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Bad request.',
|
message: 'Bad request.',
|
||||||
name: 'BadRequest',
|
name: 'BadRequest',
|
||||||
@@ -657,33 +688,33 @@ describe('Group Model', () => {
|
|||||||
emails.push(`user-${i}@example.com`);
|
emails.push(`user-${i}@example.com`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Group.validateInvitations(uuids, emails, res);
|
await Group.validateInvitations({uuids, emails}, res);
|
||||||
expect(res.t).to.not.be.called;
|
expect(res.t).to.not.be.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('does not throw an error if only user ids are passed in', async () => {
|
it('does not throw an error if only user ids are passed in', async () => {
|
||||||
await Group.validateInvitations(['user-id', 'user-id2'], null, res);
|
await Group.validateInvitations({uuids: ['user-id', 'user-id2']}, res);
|
||||||
expect(res.t).to.not.be.called;
|
expect(res.t).to.not.be.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw an error if only emails are passed in', async () => {
|
it('does not throw an error if only emails are passed in', async () => {
|
||||||
await Group.validateInvitations(null, ['user1@example.com', 'user2@example.com'], res);
|
await Group.validateInvitations({emails: ['user1@example.com', 'user2@example.com']}, res);
|
||||||
expect(res.t).to.not.be.called;
|
expect(res.t).to.not.be.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw an error if both uuids and emails are passed in', async () => {
|
it('does not throw an error if both uuids and emails are passed in', async () => {
|
||||||
await Group.validateInvitations(['user-id', 'user-id2'], ['user1@example.com', 'user2@example.com'], res);
|
await Group.validateInvitations({uuids: ['user-id', 'user-id2'], emails: ['user1@example.com', 'user2@example.com']}, res);
|
||||||
expect(res.t).to.not.be.called;
|
expect(res.t).to.not.be.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw an error if uuids are passed in and emails are an empty array', async () => {
|
it('does not throw an error if uuids are passed in and emails are an empty array', async () => {
|
||||||
await Group.validateInvitations(['user-id', 'user-id2'], [], res);
|
await Group.validateInvitations({uuids: ['user-id', 'user-id2'], emails: []}, res);
|
||||||
expect(res.t).to.not.be.called;
|
expect(res.t).to.not.be.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw an error if emails are passed in and uuids are an empty array', async () => {
|
it('does not throw an error if emails are passed in and uuids are an empty array', async () => {
|
||||||
await Group.validateInvitations([], ['user1@example.com', 'user2@example.com'], res);
|
await Group.validateInvitations({uuids: [], emails: ['user1@example.com', 'user2@example.com']}, res);
|
||||||
expect(res.t).to.not.be.called;
|
expect(res.t).to.not.be.called;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1163,16 +1194,17 @@ describe('Group Model', () => {
|
|||||||
expect(party.quest.members).to.eql(expectedQuestMembers);
|
expect(party.quest.members).to.eql(expectedQuestMembers);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('applies updates to user object directly if user is participating', async () => {
|
it('applies updates to user object directly if user is participating (without resetting progress, except progress.down)', async () => {
|
||||||
await party.startQuest(participatingMember);
|
await party.startQuest(participatingMember);
|
||||||
|
|
||||||
expect(participatingMember.party.quest.key).to.eql('whale');
|
expect(participatingMember.party.quest.key).to.eql('whale');
|
||||||
|
expect(participatingMember.party.quest.progress.up).to.eql(10);
|
||||||
expect(participatingMember.party.quest.progress.down).to.eql(0);
|
expect(participatingMember.party.quest.progress.down).to.eql(0);
|
||||||
expect(participatingMember.party.quest.progress.collectedItems).to.eql(0);
|
expect(participatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||||
expect(participatingMember.party.quest.completed).to.eql(null);
|
expect(participatingMember.party.quest.completed).to.eql(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('applies updates to other participating members', async () => {
|
it('applies updates to other participating members (without resetting progress, except progress.down)', async () => {
|
||||||
await party.startQuest(nonParticipatingMember);
|
await party.startQuest(nonParticipatingMember);
|
||||||
|
|
||||||
questLeader = await User.findById(questLeader._id);
|
questLeader = await User.findById(questLeader._id);
|
||||||
@@ -1180,18 +1212,21 @@ describe('Group Model', () => {
|
|||||||
sleepingParticipatingMember = await User.findById(sleepingParticipatingMember._id);
|
sleepingParticipatingMember = await User.findById(sleepingParticipatingMember._id);
|
||||||
|
|
||||||
expect(participatingMember.party.quest.key).to.eql('whale');
|
expect(participatingMember.party.quest.key).to.eql('whale');
|
||||||
|
expect(participatingMember.party.quest.progress.up).to.eql(10);
|
||||||
expect(participatingMember.party.quest.progress.down).to.eql(0);
|
expect(participatingMember.party.quest.progress.down).to.eql(0);
|
||||||
expect(participatingMember.party.quest.progress.collectedItems).to.eql(0);
|
expect(participatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||||
expect(participatingMember.party.quest.completed).to.eql(null);
|
expect(participatingMember.party.quest.completed).to.eql(null);
|
||||||
|
|
||||||
expect(sleepingParticipatingMember.party.quest.key).to.eql('whale');
|
expect(sleepingParticipatingMember.party.quest.key).to.eql('whale');
|
||||||
|
expect(sleepingParticipatingMember.party.quest.progress.up).to.eql(10);
|
||||||
expect(sleepingParticipatingMember.party.quest.progress.down).to.eql(0);
|
expect(sleepingParticipatingMember.party.quest.progress.down).to.eql(0);
|
||||||
expect(sleepingParticipatingMember.party.quest.progress.collectedItems).to.eql(0);
|
expect(sleepingParticipatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||||
expect(sleepingParticipatingMember.party.quest.completed).to.eql(null);
|
expect(sleepingParticipatingMember.party.quest.completed).to.eql(null);
|
||||||
|
|
||||||
expect(questLeader.party.quest.key).to.eql('whale');
|
expect(questLeader.party.quest.key).to.eql('whale');
|
||||||
|
expect(questLeader.party.quest.progress.up).to.eql(10);
|
||||||
expect(questLeader.party.quest.progress.down).to.eql(0);
|
expect(questLeader.party.quest.progress.down).to.eql(0);
|
||||||
expect(questLeader.party.quest.progress.collectedItems).to.eql(0);
|
expect(questLeader.party.quest.progress.collectedItems).to.eql(5);
|
||||||
expect(questLeader.party.quest.completed).to.eql(null);
|
expect(questLeader.party.quest.completed).to.eql(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1202,6 +1237,9 @@ describe('Group Model', () => {
|
|||||||
undecidedMember = await User.findById(undecidedMember._id);
|
undecidedMember = await User.findById(undecidedMember._id);
|
||||||
|
|
||||||
expect(nonParticipatingMember.party.quest.key).to.not.eql('whale');
|
expect(nonParticipatingMember.party.quest.key).to.not.eql('whale');
|
||||||
|
expect(nonParticipatingMember.party.quest.progress.up).to.eql(10);
|
||||||
|
expect(nonParticipatingMember.party.quest.progress.down).to.eql(8);
|
||||||
|
expect(nonParticipatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||||
expect(undecidedMember.party.quest.key).to.not.eql('whale');
|
expect(undecidedMember.party.quest.key).to.not.eql('whale');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1369,8 +1407,9 @@ describe('Group Model', () => {
|
|||||||
let userQuest = participatingMember.party.quest;
|
let userQuest = participatingMember.party.quest;
|
||||||
|
|
||||||
expect(userQuest.key).to.eql('whale');
|
expect(userQuest.key).to.eql('whale');
|
||||||
|
expect(userQuest.progress.up).to.eql(10);
|
||||||
expect(userQuest.progress.down).to.eql(0);
|
expect(userQuest.progress.down).to.eql(0);
|
||||||
expect(userQuest.progress.collectedItems).to.eql(0);
|
expect(userQuest.progress.collectedItems).to.eql(5);
|
||||||
expect(userQuest.completed).to.eql(null);
|
expect(userQuest.completed).to.eql(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1670,16 +1709,23 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets user quest object to a clean state', async () => {
|
it('updates participating members quest object to a clean state (except for progress)', async () => {
|
||||||
await party.finishQuest(quest);
|
await party.finishQuest(quest);
|
||||||
|
|
||||||
let updatedLeader = await User.findById(questLeader._id);
|
questLeader = await User.findById(questLeader._id);
|
||||||
|
participatingMember = await User.findById(participatingMember._id);
|
||||||
|
|
||||||
expect(updatedLeader.party.quest.completed).to.eql('whale');
|
expect(questLeader.party.quest.completed).to.eql('whale');
|
||||||
expect(updatedLeader.party.quest.progress.up).to.eql(0);
|
expect(questLeader.party.quest.progress.up).to.eql(10);
|
||||||
expect(updatedLeader.party.quest.progress.down).to.eql(0);
|
expect(questLeader.party.quest.progress.down).to.eql(8);
|
||||||
expect(updatedLeader.party.quest.progress.collectedItems).to.eql(0);
|
expect(questLeader.party.quest.progress.collectedItems).to.eql(5);
|
||||||
expect(updatedLeader.party.quest.RSVPNeeded).to.eql(false);
|
expect(questLeader.party.quest.RSVPNeeded).to.eql(false);
|
||||||
|
|
||||||
|
expect(participatingMember.party.quest.completed).to.eql('whale');
|
||||||
|
expect(participatingMember.party.quest.progress.up).to.eql(10);
|
||||||
|
expect(participatingMember.party.quest.progress.down).to.eql(8);
|
||||||
|
expect(participatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||||
|
expect(participatingMember.party.quest.RSVPNeeded).to.eql(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1843,6 +1889,62 @@ describe('Group Model', () => {
|
|||||||
expect(options.chat).to.eql(chat);
|
expect(options.chat).to.eql(chat);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends webhooks for users with webhooks triggered by system messages', async () => {
|
||||||
|
let guild = new Group({
|
||||||
|
name: 'some guild',
|
||||||
|
type: 'guild',
|
||||||
|
});
|
||||||
|
|
||||||
|
let memberWithWebhook = new User({
|
||||||
|
guilds: [guild._id],
|
||||||
|
webhooks: [{
|
||||||
|
type: 'groupChatReceived',
|
||||||
|
url: 'http://someurl.com',
|
||||||
|
options: {
|
||||||
|
groupId: guild._id,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
let memberWithoutWebhook = new User({
|
||||||
|
guilds: [guild._id],
|
||||||
|
});
|
||||||
|
let nonMemberWithWebhooks = new User({
|
||||||
|
webhooks: [{
|
||||||
|
type: 'groupChatReceived',
|
||||||
|
url: 'http://a-different-url.com',
|
||||||
|
options: {
|
||||||
|
groupId: generateUUID(),
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
memberWithWebhook.save(),
|
||||||
|
memberWithoutWebhook.save(),
|
||||||
|
nonMemberWithWebhooks.save(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
guild.leader = memberWithWebhook._id;
|
||||||
|
|
||||||
|
await guild.save();
|
||||||
|
|
||||||
|
const groupMessage = guild.sendChat('Test message.');
|
||||||
|
await groupMessage.save();
|
||||||
|
|
||||||
|
await sleep();
|
||||||
|
|
||||||
|
expect(groupChatReceivedWebhook.send).to.be.calledOnce;
|
||||||
|
|
||||||
|
let args = groupChatReceivedWebhook.send.args[0];
|
||||||
|
let webhooks = args[0].webhooks;
|
||||||
|
let options = args[1];
|
||||||
|
|
||||||
|
expect(webhooks).to.have.a.lengthOf(1);
|
||||||
|
expect(webhooks[0].id).to.eql(memberWithWebhook.webhooks[0].id);
|
||||||
|
expect(options.group).to.eql(guild);
|
||||||
|
expect(options.chat).to.eql(groupMessage);
|
||||||
|
});
|
||||||
|
|
||||||
it('sends webhooks for each user with webhooks in group', async () => {
|
it('sends webhooks for each user with webhooks in group', async () => {
|
||||||
let guild = new Group({
|
let guild = new Group({
|
||||||
name: 'some guild',
|
name: 'some guild',
|
||||||
|
|||||||
@@ -47,6 +47,14 @@ describe('GET /challenges/:challengeId', () => {
|
|||||||
_id: groupLeader._id,
|
_id: groupLeader._id,
|
||||||
id: groupLeader._id,
|
id: groupLeader._id,
|
||||||
profile: {name: groupLeader.profile.name},
|
profile: {name: groupLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: groupLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(chal.group).to.eql({
|
expect(chal.group).to.eql({
|
||||||
_id: group._id,
|
_id: group._id,
|
||||||
@@ -105,6 +113,14 @@ describe('GET /challenges/:challengeId', () => {
|
|||||||
_id: challengeLeader._id,
|
_id: challengeLeader._id,
|
||||||
id: challengeLeader._id,
|
id: challengeLeader._id,
|
||||||
profile: {name: challengeLeader.profile.name},
|
profile: {name: challengeLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: challengeLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(chal.group).to.eql({
|
expect(chal.group).to.eql({
|
||||||
_id: group._id,
|
_id: group._id,
|
||||||
@@ -131,6 +147,14 @@ describe('GET /challenges/:challengeId', () => {
|
|||||||
_id: challengeLeader._id,
|
_id: challengeLeader._id,
|
||||||
id: challengeLeader._id,
|
id: challengeLeader._id,
|
||||||
profile: {name: challengeLeader.profile.name},
|
profile: {name: challengeLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: challengeLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -179,6 +203,14 @@ describe('GET /challenges/:challengeId', () => {
|
|||||||
_id: challengeLeader._id,
|
_id: challengeLeader._id,
|
||||||
id: challengeLeader._id,
|
id: challengeLeader._id,
|
||||||
profile: {name: challengeLeader.profile.name},
|
profile: {name: challengeLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: challengeLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(chal.group).to.eql({
|
expect(chal.group).to.eql({
|
||||||
_id: group._id,
|
_id: group._id,
|
||||||
@@ -205,6 +237,14 @@ describe('GET /challenges/:challengeId', () => {
|
|||||||
_id: challengeLeader._id,
|
_id: challengeLeader._id,
|
||||||
id: challengeLeader._id,
|
id: challengeLeader._id,
|
||||||
profile: {name: challengeLeader.profile.name},
|
profile: {name: challengeLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: challengeLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ describe('GET /challenges/:challengeId/export/csv', () => {
|
|||||||
const sortedMembers = _.sortBy([members[0], members[1], members[2], groupLeader], '_id');
|
const sortedMembers = _.sortBy([members[0], members[1], members[2], groupLeader], '_id');
|
||||||
const splitRes = res.split('\n');
|
const splitRes = res.split('\n');
|
||||||
|
|
||||||
expect(splitRes[0]).to.equal('UUID,name,Task,Value,Notes,Streak,Task,Value,Notes,Streak');
|
expect(splitRes[0]).to.equal('UUID,Display Name,Username,Task,Value,Notes,Streak,Task,Value,Notes,Streak');
|
||||||
expect(splitRes[1]).to.equal(`${sortedMembers[0]._id},${sortedMembers[0].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[1]).to.equal(`${sortedMembers[0]._id},${sortedMembers[0].profile.name},${sortedMembers[0].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[2]).to.equal(`${sortedMembers[1]._id},${sortedMembers[1].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[2]).to.equal(`${sortedMembers[1]._id},${sortedMembers[1].profile.name},${sortedMembers[1].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[3]).to.equal(`${sortedMembers[2]._id},${sortedMembers[2].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[3]).to.equal(`${sortedMembers[2]._id},${sortedMembers[2].profile.name},${sortedMembers[2].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[4]).to.equal(`${sortedMembers[3]._id},${sortedMembers[3].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[4]).to.equal(`${sortedMembers[3]._id},${sortedMembers[3].profile.name},${sortedMembers[3].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[5]).to.equal('');
|
expect(splitRes[5]).to.equal('');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -78,10 +78,10 @@ describe('GET /challenges/:challengeId/export/csv', () => {
|
|||||||
const res = await members[1].get(`/challenges/${challenge._id}/export/csv`);
|
const res = await members[1].get(`/challenges/${challenge._id}/export/csv`);
|
||||||
const sortedMembers = _.sortBy([members[1], members[2], groupLeader], '_id');
|
const sortedMembers = _.sortBy([members[1], members[2], groupLeader], '_id');
|
||||||
const splitRes = res.split('\n');
|
const splitRes = res.split('\n');
|
||||||
expect(splitRes[0]).to.equal('UUID,name,Task,Value,Notes,Streak,Task,Value,Notes,Streak');
|
expect(splitRes[0]).to.equal('UUID,Display Name,Username,Task,Value,Notes,Streak,Task,Value,Notes,Streak');
|
||||||
expect(splitRes[1]).to.equal(`${sortedMembers[0]._id},${sortedMembers[0].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[1]).to.equal(`${sortedMembers[0]._id},${sortedMembers[0].profile.name},${sortedMembers[0].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[2]).to.equal(`${sortedMembers[1]._id},${sortedMembers[1].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[2]).to.equal(`${sortedMembers[1]._id},${sortedMembers[1].profile.name},${sortedMembers[1].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[3]).to.equal(`${sortedMembers[2]._id},${sortedMembers[2].profile.name},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
expect(splitRes[3]).to.equal(`${sortedMembers[2]._id},${sortedMembers[2].profile.name},${sortedMembers[2].auth.local.username},habit:Task 1,0,,0,todo:Task 2,0,,0`);
|
||||||
expect(splitRes[4]).to.equal('');
|
expect(splitRes[4]).to.equal('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,6 +60,14 @@ describe('GET /challenges/:challengeId/members', () => {
|
|||||||
_id: groupLeader._id,
|
_id: groupLeader._id,
|
||||||
id: groupLeader._id,
|
id: groupLeader._id,
|
||||||
profile: {name: groupLeader.profile.name},
|
profile: {name: groupLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: groupLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -73,8 +81,16 @@ describe('GET /challenges/:challengeId/members', () => {
|
|||||||
_id: leader._id,
|
_id: leader._id,
|
||||||
id: leader._id,
|
id: leader._id,
|
||||||
profile: {name: leader.profile.name},
|
profile: {name: leader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: leader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(res[0]).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(res[0]).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(res[0].profile).to.have.all.keys(['name']);
|
expect(res[0].profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -88,8 +104,16 @@ describe('GET /challenges/:challengeId/members', () => {
|
|||||||
_id: anotherUser._id,
|
_id: anotherUser._id,
|
||||||
id: anotherUser._id,
|
id: anotherUser._id,
|
||||||
profile: {name: anotherUser.profile.name},
|
profile: {name: anotherUser.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: anotherUser.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(res[0]).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(res[0]).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(res[0].profile).to.have.all.keys(['name']);
|
expect(res[0].profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -107,7 +131,7 @@ describe('GET /challenges/:challengeId/members', () => {
|
|||||||
let res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=not-true`);
|
let res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=not-true`);
|
||||||
expect(res.length).to.equal(30);
|
expect(res.length).to.equal(30);
|
||||||
res.forEach(member => {
|
res.forEach(member => {
|
||||||
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(member.profile).to.have.all.keys(['name']);
|
expect(member.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -126,7 +150,7 @@ describe('GET /challenges/:challengeId/members', () => {
|
|||||||
let res = await user.get(`/challenges/${challenge._id}/members`);
|
let res = await user.get(`/challenges/${challenge._id}/members`);
|
||||||
expect(res.length).to.equal(30);
|
expect(res.length).to.equal(30);
|
||||||
res.forEach(member => {
|
res.forEach(member => {
|
||||||
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(member.profile).to.have.all.keys(['name']);
|
expect(member.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -145,7 +169,7 @@ describe('GET /challenges/:challengeId/members', () => {
|
|||||||
let res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=true`);
|
let res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=true`);
|
||||||
expect(res.length).to.equal(32);
|
expect(res.length).to.equal(32);
|
||||||
res.forEach(member => {
|
res.forEach(member => {
|
||||||
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(member.profile).to.have.all.keys(['name']);
|
expect(member.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ describe('GET /challenges/:challengeId/members/:memberId', () => {
|
|||||||
await groupLeader.post(`/tasks/challenge/${challenge._id}`, [{type: 'habit', text: taskText}]);
|
await groupLeader.post(`/tasks/challenge/${challenge._id}`, [{type: 'habit', text: taskText}]);
|
||||||
|
|
||||||
let memberProgress = await user.get(`/challenges/${challenge._id}/members/${groupLeader._id}`);
|
let memberProgress = await user.get(`/challenges/${challenge._id}/members/${groupLeader._id}`);
|
||||||
expect(memberProgress).to.have.all.keys(['_id', 'id', 'profile', 'tasks']);
|
expect(memberProgress).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile', 'tasks']);
|
||||||
expect(memberProgress.profile).to.have.all.keys(['name']);
|
expect(memberProgress.profile).to.have.all.keys(['name']);
|
||||||
expect(memberProgress.tasks.length).to.equal(1);
|
expect(memberProgress.tasks.length).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -46,6 +54,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,6 +74,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -65,6 +89,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -125,6 +157,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: privateGuild.leader._id,
|
_id: privateGuild.leader._id,
|
||||||
id: privateGuild.leader._id,
|
id: privateGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -132,6 +172,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: privateGuild.leader._id,
|
_id: privateGuild.leader._id,
|
||||||
id: privateGuild.leader._id,
|
id: privateGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -235,6 +283,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: party.leader._id,
|
_id: party.leader._id,
|
||||||
id: party.leader._id,
|
id: party.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -242,6 +298,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: party.leader._id,
|
_id: party.leader._id,
|
||||||
id: party.leader._id,
|
id: party.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -254,6 +318,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: party.leader._id,
|
_id: party.leader._id,
|
||||||
id: party.leader._id,
|
id: party.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -261,6 +333,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: party.leader._id,
|
_id: party.leader._id,
|
||||||
id: party.leader._id,
|
id: party.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -288,6 +368,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: user._id,
|
_id: user._id,
|
||||||
id: user._id,
|
id: user._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -295,6 +383,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: user._id,
|
_id: user._id,
|
||||||
id: user._id,
|
id: user._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -307,6 +403,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: user._id,
|
_id: user._id,
|
||||||
id: user._id,
|
id: user._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||||
expect(foundChallenge2).to.exist;
|
expect(foundChallenge2).to.exist;
|
||||||
@@ -314,6 +418,14 @@ describe('GET challenges/groups/:groupId', () => {
|
|||||||
_id: user._id,
|
_id: user._id,
|
||||||
id: user._id,
|
id: user._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ describe('GET challenges/user', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(foundChallenge.group).to.eql({
|
expect(foundChallenge.group).to.eql({
|
||||||
_id: publicGuild._id,
|
_id: publicGuild._id,
|
||||||
@@ -62,6 +70,14 @@ describe('GET challenges/user', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(foundChallenge1.group).to.eql({
|
expect(foundChallenge1.group).to.eql({
|
||||||
_id: publicGuild._id,
|
_id: publicGuild._id,
|
||||||
@@ -79,6 +95,14 @@ describe('GET challenges/user', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(foundChallenge2.group).to.eql({
|
expect(foundChallenge2.group).to.eql({
|
||||||
_id: publicGuild._id,
|
_id: publicGuild._id,
|
||||||
@@ -101,6 +125,14 @@ describe('GET challenges/user', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(foundChallenge1.group).to.eql({
|
expect(foundChallenge1.group).to.eql({
|
||||||
_id: publicGuild._id,
|
_id: publicGuild._id,
|
||||||
@@ -118,6 +150,14 @@ describe('GET challenges/user', () => {
|
|||||||
_id: publicGuild.leader._id,
|
_id: publicGuild.leader._id,
|
||||||
id: publicGuild.leader._id,
|
id: publicGuild.leader._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(foundChallenge2.group).to.eql({
|
expect(foundChallenge2.group).to.eql({
|
||||||
_id: publicGuild._id,
|
_id: publicGuild._id,
|
||||||
|
|||||||
@@ -79,6 +79,14 @@ describe('POST /challenges/:challengeId/join', () => {
|
|||||||
_id: groupLeader._id,
|
_id: groupLeader._id,
|
||||||
id: groupLeader._id,
|
id: groupLeader._id,
|
||||||
profile: {name: groupLeader.profile.name},
|
profile: {name: groupLeader.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: groupLeader.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(res.name).to.equal(challenge.name);
|
expect(res.name).to.equal(challenge.name);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -79,6 +79,14 @@ describe('PUT /challenges/:challengeId', () => {
|
|||||||
_id: member._id,
|
_id: member._id,
|
||||||
id: member._id,
|
id: member._id,
|
||||||
profile: {name: member.profile.name},
|
profile: {name: member.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: member.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(res.name).to.equal('New Challenge Name');
|
expect(res.name).to.equal('New Challenge Name');
|
||||||
expect(res.description).to.equal('New challenge description.');
|
expect(res.description).to.equal('New challenge description.');
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ describe('POST /chat/:chatId/flag', () => {
|
|||||||
|
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
||||||
text: `${user.profile.name} (${user.id}; language: en) flagged a message`,
|
text: `${user.profile.name} (${user.id}; language: en) flagged a group message`,
|
||||||
attachments: [{
|
attachments: [{
|
||||||
fallback: 'Flag Message',
|
fallback: 'Flag Message',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
author_name: `${anotherUser.profile.name} - ${anotherUser.auth.local.email} - ${anotherUser._id}\n${timestamp}`,
|
author_name: `@${anotherUser.auth.local.username} ${anotherUser.profile.name} (${anotherUser.auth.local.email}; ${anotherUser._id})\n${timestamp}`,
|
||||||
title: 'Flag in Test Guild',
|
title: 'Flag in Test Guild',
|
||||||
title_link: `${BASE_URL}/groups/guild/${group._id}`,
|
title_link: `${BASE_URL}/groups/guild/${group._id}`,
|
||||||
text: TEST_MESSAGE,
|
text: TEST_MESSAGE,
|
||||||
@@ -98,11 +98,11 @@ describe('POST /chat/:chatId/flag', () => {
|
|||||||
|
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
||||||
text: `${newUser.profile.name} (${newUser.id}; language: en) flagged a message`,
|
text: `${newUser.profile.name} (${newUser.id}; language: en) flagged a group message`,
|
||||||
attachments: [{
|
attachments: [{
|
||||||
fallback: 'Flag Message',
|
fallback: 'Flag Message',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
author_name: `${newUser.profile.name} - ${newUser.auth.local.email} - ${newUser._id}\n${timestamp}`,
|
author_name: `@${newUser.auth.local.username} ${newUser.profile.name} (${newUser.auth.local.email}; ${newUser._id})\n${timestamp}`,
|
||||||
title: 'Flag in Test Guild',
|
title: 'Flag in Test Guild',
|
||||||
title_link: `${BASE_URL}/groups/guild/${group._id}`,
|
title_link: `${BASE_URL}/groups/guild/${group._id}`,
|
||||||
text: TEST_MESSAGE,
|
text: TEST_MESSAGE,
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ describe('POST /chat', () => {
|
|||||||
attachments: [{
|
attachments: [{
|
||||||
fallback: 'Slur Message',
|
fallback: 'Slur Message',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
author_name: `${user.profile.name} - ${user.auth.local.email} - ${user._id}`,
|
author_name: `@${user.auth.local.username} ${user.profile.name} (${user.auth.local.email}; ${user._id})`,
|
||||||
title: 'Slur in Test Guild',
|
title: 'Slur in Test Guild',
|
||||||
title_link: `${BASE_URL}/groups/guild/${groupWithChat.id}`,
|
title_link: `${BASE_URL}/groups/guild/${groupWithChat.id}`,
|
||||||
text: testSlurMessage,
|
text: testSlurMessage,
|
||||||
@@ -310,7 +310,7 @@ describe('POST /chat', () => {
|
|||||||
attachments: [{
|
attachments: [{
|
||||||
fallback: 'Slur Message',
|
fallback: 'Slur Message',
|
||||||
color: 'danger',
|
color: 'danger',
|
||||||
author_name: `${members[0].profile.name} - ${members[0].auth.local.email} - ${members[0]._id}`,
|
author_name: `@${members[0].auth.local.username} ${members[0].profile.name} (${members[0].auth.local.email}; ${members[0]._id})`,
|
||||||
title: 'Slur in Party - (private party)',
|
title: 'Slur in Party - (private party)',
|
||||||
title_link: undefined,
|
title_link: undefined,
|
||||||
text: testSlurMessage,
|
text: testSlurMessage,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
|
|||||||
.to.eventually.be.rejected.and.eql({
|
.to.eventually.be.rejected.and.eql({
|
||||||
code: 400,
|
code: 400,
|
||||||
error: 'BadRequest',
|
error: 'BadRequest',
|
||||||
message: t('messageCannotFlagSystemMessages', {communityManagerEmail: config.EMAILS.COMMUNITY_MANAGER_EMAIL}),
|
message: t('messageCannotFlagSystemMessages', {communityManagerEmail: config.EMAILS_COMMUNITY_MANAGER_EMAIL}),
|
||||||
});
|
});
|
||||||
// let messages = await members[0].get(`/groups/${group._id}/chat`);
|
// let messages = await members[0].get(`/groups/${group._id}/chat`);
|
||||||
// expect(messages[0].id).to.eql(skillMsg.id);
|
// expect(messages[0].id).to.eql(skillMsg.id);
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ describe('GET /groups', () => {
|
|||||||
let page2 = await expect(user.get('/groups?type=publicGuilds&paginate=true&page=2'))
|
let page2 = await expect(user.get('/groups?type=publicGuilds&paginate=true&page=2'))
|
||||||
.to.eventually.have.a.lengthOf(1 + 4); // 1 created now, 4 by other tests
|
.to.eventually.have.a.lengthOf(1 + 4); // 1 created now, 4 by other tests
|
||||||
expect(page2[4].name).to.equal('guild with less members');
|
expect(page2[4].name).to.equal('guild with less members');
|
||||||
});
|
}).timeout(10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns all the user\'s guilds when guilds passed in as query', async () => {
|
it('returns all the user\'s guilds when guilds passed in as query', async () => {
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ describe('GET /groups/:groupId/invites', () => {
|
|||||||
_id: invited._id,
|
_id: invited._id,
|
||||||
id: invited._id,
|
id: invited._id,
|
||||||
profile: {name: invited.profile.name},
|
profile: {name: invited.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: invited.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,7 +66,7 @@ describe('GET /groups/:groupId/invites', () => {
|
|||||||
let invited = await generateUser();
|
let invited = await generateUser();
|
||||||
await user.post(`/groups/${group._id}/invite`, {uuids: [invited._id]});
|
await user.post(`/groups/${group._id}/invite`, {uuids: [invited._id]});
|
||||||
let res = await user.get('/groups/party/invites');
|
let res = await user.get('/groups/party/invites');
|
||||||
expect(res[0]).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(res[0]).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(res[0].profile).to.have.all.keys(['name']);
|
expect(res[0].profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -76,7 +84,7 @@ describe('GET /groups/:groupId/invites', () => {
|
|||||||
let res = await leader.get(`/groups/${group._id}/invites`);
|
let res = await leader.get(`/groups/${group._id}/invites`);
|
||||||
expect(res.length).to.equal(30);
|
expect(res.length).to.equal(30);
|
||||||
res.forEach(member => {
|
res.forEach(member => {
|
||||||
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(member.profile).to.have.all.keys(['name']);
|
expect(member.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
}).timeout(10000);
|
}).timeout(10000);
|
||||||
|
|||||||
@@ -56,13 +56,21 @@ describe('GET /groups/:groupId/members', () => {
|
|||||||
_id: user._id,
|
_id: user._id,
|
||||||
id: user._id,
|
id: user._id,
|
||||||
profile: {name: user.profile.name},
|
profile: {name: user.profile.name},
|
||||||
|
auth: {
|
||||||
|
local: {
|
||||||
|
username: user.auth.local.username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
verifiedUsername: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('populates only some fields', async () => {
|
it('populates only some fields', async () => {
|
||||||
await generateGroup(user, {type: 'party', name: generateUUID()});
|
await generateGroup(user, {type: 'party', name: generateUUID()});
|
||||||
let res = await user.get('/groups/party/members');
|
let res = await user.get('/groups/party/members');
|
||||||
expect(res[0]).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(res[0]).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(res[0].profile).to.have.all.keys(['name']);
|
expect(res[0].profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -74,7 +82,7 @@ describe('GET /groups/:groupId/members', () => {
|
|||||||
'_id', 'id', 'preferences', 'profile', 'stats', 'achievements', 'party',
|
'_id', 'id', 'preferences', 'profile', 'stats', 'achievements', 'party',
|
||||||
'backer', 'contributor', 'auth', 'items', 'inbox', 'loginIncentives', 'flags',
|
'backer', 'contributor', 'auth', 'items', 'inbox', 'loginIncentives', 'flags',
|
||||||
]);
|
]);
|
||||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
expect(Object.keys(memberRes.auth)).to.eql(['local', 'timestamps']);
|
||||||
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||||
'size', 'hair', 'skin', 'shirt',
|
'size', 'hair', 'skin', 'shirt',
|
||||||
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
||||||
@@ -95,7 +103,7 @@ describe('GET /groups/:groupId/members', () => {
|
|||||||
'_id', 'id', 'preferences', 'profile', 'stats', 'achievements', 'party',
|
'_id', 'id', 'preferences', 'profile', 'stats', 'achievements', 'party',
|
||||||
'backer', 'contributor', 'auth', 'items', 'inbox', 'loginIncentives', 'flags',
|
'backer', 'contributor', 'auth', 'items', 'inbox', 'loginIncentives', 'flags',
|
||||||
]);
|
]);
|
||||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
expect(Object.keys(memberRes.auth)).to.eql(['local', 'timestamps']);
|
||||||
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||||
'size', 'hair', 'skin', 'shirt',
|
'size', 'hair', 'skin', 'shirt',
|
||||||
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
||||||
@@ -120,7 +128,7 @@ describe('GET /groups/:groupId/members', () => {
|
|||||||
let res = await user.get('/groups/party/members');
|
let res = await user.get('/groups/party/members');
|
||||||
expect(res.length).to.equal(30);
|
expect(res.length).to.equal(30);
|
||||||
res.forEach(member => {
|
res.forEach(member => {
|
||||||
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(member.profile).to.have.all.keys(['name']);
|
expect(member.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -137,7 +145,7 @@ describe('GET /groups/:groupId/members', () => {
|
|||||||
let res = await user.get('/groups/party/members?includeAllMembers=true');
|
let res = await user.get('/groups/party/members?includeAllMembers=true');
|
||||||
expect(res.length).to.equal(30);
|
expect(res.length).to.equal(30);
|
||||||
res.forEach(member => {
|
res.forEach(member => {
|
||||||
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
|
||||||
expect(member.profile).to.have.all.keys(['name']);
|
expect(member.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,6 +23,73 @@ describe('Post /groups/:groupId/invite', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('username invites', () => {
|
||||||
|
it('returns an error when invited user is not found', async () => {
|
||||||
|
const fakeID = 'fakeuserid';
|
||||||
|
|
||||||
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
||||||
|
usernames: [fakeID],
|
||||||
|
}))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: t('userWithUsernameNotFound', {username: fakeID}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns an error when inviting yourself to a group', async () => {
|
||||||
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
||||||
|
usernames: [inviter.auth.local.lowerCaseUsername],
|
||||||
|
}))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('cannotInviteSelfToGroup'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invites a user to a group by username', async () => {
|
||||||
|
const userToInvite = await generateUser();
|
||||||
|
|
||||||
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
||||||
|
usernames: [userToInvite.auth.local.lowerCaseUsername],
|
||||||
|
})).to.eventually.deep.equal([{
|
||||||
|
id: group._id,
|
||||||
|
name: groupName,
|
||||||
|
inviter: inviter._id,
|
||||||
|
publicGuild: false,
|
||||||
|
}]);
|
||||||
|
|
||||||
|
await expect(userToInvite.get('/user'))
|
||||||
|
.to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invites multiple users to a group by uuid', async () => {
|
||||||
|
const userToInvite = await generateUser();
|
||||||
|
const userToInvite2 = await generateUser();
|
||||||
|
|
||||||
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
||||||
|
usernames: [userToInvite.auth.local.lowerCaseUsername, userToInvite2.auth.local.lowerCaseUsername],
|
||||||
|
})).to.eventually.deep.equal([
|
||||||
|
{
|
||||||
|
id: group._id,
|
||||||
|
name: groupName,
|
||||||
|
inviter: inviter._id,
|
||||||
|
publicGuild: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: group._id,
|
||||||
|
name: groupName,
|
||||||
|
inviter: inviter._id,
|
||||||
|
publicGuild: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await expect(userToInvite.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
||||||
|
await expect(userToInvite2.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('user id invites', () => {
|
describe('user id invites', () => {
|
||||||
it('returns an error when inviter has no chat privileges', async () => {
|
it('returns an error when inviter has no chat privileges', async () => {
|
||||||
let inviterMuted = await inviter.update({'flags.chatRevoked': true});
|
let inviterMuted = await inviter.update({'flags.chatRevoked': true});
|
||||||
@@ -93,7 +160,7 @@ describe('Post /groups/:groupId/invite', () => {
|
|||||||
.to.eventually.be.rejected.and.eql({
|
.to.eventually.be.rejected.and.eql({
|
||||||
code: 400,
|
code: 400,
|
||||||
error: 'BadRequest',
|
error: 'BadRequest',
|
||||||
message: t('inviteMissingUuid'),
|
message: t('inviteMustNotBeEmpty'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -228,7 +295,7 @@ describe('Post /groups/:groupId/invite', () => {
|
|||||||
.to.eventually.be.rejected.and.eql({
|
.to.eventually.be.rejected.and.eql({
|
||||||
code: 400,
|
code: 400,
|
||||||
error: 'BadRequest',
|
error: 'BadRequest',
|
||||||
message: t('inviteMissingEmail'),
|
message: t('inviteMustNotBeEmpty'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -266,7 +333,7 @@ describe('Post /groups/:groupId/invite', () => {
|
|||||||
.to.eventually.be.rejected.and.eql({
|
.to.eventually.be.rejected.and.eql({
|
||||||
code: 401,
|
code: 401,
|
||||||
error: 'NotAuthorized',
|
error: 'NotAuthorized',
|
||||||
message: t('inviteLimitReached', {techAssistanceEmail: nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL')}),
|
message: t('inviteLimitReached', {techAssistanceEmail: nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL')}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ describe('GET /heroes/:heroId', () => {
|
|||||||
|
|
||||||
it('validates req.params.heroId', async () => {
|
it('validates req.params.heroId', async () => {
|
||||||
await expect(user.get('/hall/heroes/invalidUUID')).to.eventually.be.rejected.and.eql({
|
await expect(user.get('/hall/heroes/invalidUUID')).to.eventually.be.rejected.and.eql({
|
||||||
code: 400,
|
code: 404,
|
||||||
error: 'BadRequest',
|
error: 'NotFound',
|
||||||
message: t('invalidReqParams'),
|
message: t('userWithIDNotFound', {userId: 'invalidUUID'}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ describe('GET /heroes/:heroId', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns only necessary hero data', async () => {
|
it('returns only necessary hero data given user id', async () => {
|
||||||
let hero = await generateUser({
|
let hero = await generateUser({
|
||||||
contributor: {tier: 23},
|
contributor: {tier: 23},
|
||||||
});
|
});
|
||||||
@@ -53,4 +53,24 @@ describe('GET /heroes/:heroId', () => {
|
|||||||
expect(heroRes.auth.local).not.to.have.keys(['salt', 'hashed_password']);
|
expect(heroRes.auth.local).not.to.have.keys(['salt', 'hashed_password']);
|
||||||
expect(heroRes.profile).to.have.all.keys(['name']);
|
expect(heroRes.profile).to.have.all.keys(['name']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns only necessary hero data given username', async () => {
|
||||||
|
let hero = await generateUser({
|
||||||
|
contributor: {tier: 23},
|
||||||
|
});
|
||||||
|
let heroRes = await user.get(`/hall/heroes/${hero.auth.local.username}`);
|
||||||
|
|
||||||
|
expect(heroRes).to.have.all.keys([ // works as: object has all and only these keys
|
||||||
|
'_id', 'id', 'balance', 'profile', 'purchased',
|
||||||
|
'contributor', 'auth', 'items',
|
||||||
|
]);
|
||||||
|
expect(heroRes.auth.local).not.to.have.keys(['salt', 'hashed_password']);
|
||||||
|
expect(heroRes.profile).to.have.all.keys(['name']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns correct hero using search with difference case', async () => {
|
||||||
|
await generateUser({}, { username: 'TestUpperCaseName123' });
|
||||||
|
let heroRes = await user.get('/hall/heroes/TestuPPerCasEName123');
|
||||||
|
expect(heroRes.auth.local.username).to.equal('TestUpperCaseName123');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ describe('GET /inbox/messages', () => {
|
|||||||
toUserId: user.id,
|
toUserId: user.id,
|
||||||
message: 'fourth',
|
message: 'fourth',
|
||||||
});
|
});
|
||||||
|
|
||||||
await user.sync();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the user inbox messages as an array of ordered messages (from most to least recent)', async () => {
|
it('returns the user inbox messages as an array of ordered messages (from most to least recent)', async () => {
|
||||||
@@ -45,4 +43,27 @@ describe('GET /inbox/messages', () => {
|
|||||||
expect(messages[2].text).to.equal('second');
|
expect(messages[2].text).to.equal('second');
|
||||||
expect(messages[3].text).to.equal('first');
|
expect(messages[3].text).to.equal('first');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns four messages when using page-query ', async () => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
promises.push(user.post('/members/send-private-message', {
|
||||||
|
toUserId: user.id,
|
||||||
|
message: 'fourth',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
const messages = await user.get('/inbox/messages?page=1');
|
||||||
|
|
||||||
|
expect(messages.length).to.equal(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns only the messages of one conversation', async () => {
|
||||||
|
const messages = await user.get(`/inbox/messages?conversation=${otherUser.id}`);
|
||||||
|
|
||||||
|
expect(messages.length).to.equal(3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ describe('GET /members/:memberId', () => {
|
|||||||
'_id', 'id', 'preferences', 'profile', 'stats', 'achievements', 'party',
|
'_id', 'id', 'preferences', 'profile', 'stats', 'achievements', 'party',
|
||||||
'backer', 'contributor', 'auth', 'items', 'inbox', 'loginIncentives', 'flags',
|
'backer', 'contributor', 'auth', 'items', 'inbox', 'loginIncentives', 'flags',
|
||||||
]);
|
]);
|
||||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
expect(Object.keys(memberRes.auth)).to.eql(['local', 'timestamps']);
|
||||||
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||||
'size', 'hair', 'skin', 'shirt',
|
'size', 'hair', 'skin', 'shirt',
|
||||||
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ describe('POST /notifications/:notificationId/read', () => {
|
|||||||
|
|
||||||
await expect(user.post(`/notifications/${dummyId}/read`)).to.eventually.be.rejected.and.eql({
|
await expect(user.post(`/notifications/${dummyId}/read`)).to.eventually.be.rejected.and.eql({
|
||||||
code: 404,
|
code: 404,
|
||||||
error: 'NotFound',
|
error: 'NotificationNotFound',
|
||||||
message: t('messageNotificationNotFound'),
|
message: t('messageNotificationNotFound'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ describe('POST /notifications/:notificationId/see', () => {
|
|||||||
|
|
||||||
await expect(user.post(`/notifications/${dummyId}/see`)).to.eventually.be.rejected.and.eql({
|
await expect(user.post(`/notifications/${dummyId}/see`)).to.eventually.be.rejected.and.eql({
|
||||||
code: 404,
|
code: 404,
|
||||||
error: 'NotFound',
|
error: 'NotificationNotFound',
|
||||||
message: t('messageNotificationNotFound'),
|
message: t('messageNotificationNotFound'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('POST /notifications/read', () => {
|
|||||||
notificationIds: [dummyId],
|
notificationIds: [dummyId],
|
||||||
})).to.eventually.be.rejected.and.eql({
|
})).to.eventually.be.rejected.and.eql({
|
||||||
code: 404,
|
code: 404,
|
||||||
error: 'NotFound',
|
error: 'NotificationNotFound',
|
||||||
message: t('messageNotificationNotFound'),
|
message: t('messageNotificationNotFound'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('POST /notifications/see', () => {
|
|||||||
notificationIds: [dummyId],
|
notificationIds: [dummyId],
|
||||||
})).to.eventually.be.rejected.and.eql({
|
})).to.eventually.be.rejected.and.eql({
|
||||||
code: 404,
|
code: 404,
|
||||||
error: 'NotFound',
|
error: 'NotificationNotFound',
|
||||||
message: t('messageNotificationNotFound'),
|
message: t('messageNotificationNotFound'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ describe('payments : amazon #subscribeCancel', () => {
|
|||||||
|
|
||||||
describe('success', () => {
|
describe('success', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
amazonSubscribeCancelStub = sinon.stub(amzLib, 'cancelSubscription').returnsPromise().resolves({});
|
amazonSubscribeCancelStub = sinon.stub(amzLib, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe('payments - amazon - #checkout', () => {
|
|||||||
|
|
||||||
describe('success', () => {
|
describe('success', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
amazonCheckoutStub = sinon.stub(amzLib, 'checkout').returnsPromise().resolves({});
|
amazonCheckoutStub = sinon.stub(amzLib, 'checkout').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe('payments - amazon - #subscribe', () => {
|
|||||||
let coupon;
|
let coupon;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
subscribeWithAmazonStub = sinon.stub(amzLib, 'subscribe').returnsPromise().resolves({});
|
subscribeWithAmazonStub = sinon.stub(amzLib, 'subscribe').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ describe('payments : apple #cancelSubscribe', () => {
|
|||||||
let cancelStub;
|
let cancelStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
cancelStub = sinon.stub(applePayments, 'cancelSubscribe').returnsPromise().resolves({});
|
cancelStub = sinon.stub(applePayments, 'cancelSubscribe').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import {generateUser, translate as t} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import applePayments from '../../../../../../website/server/libs/payments/apple';
|
||||||
|
|
||||||
|
describe('payments : apple #norenewsubscribe', () => {
|
||||||
|
let endpoint = '/iap/ios/norenew-subscribe';
|
||||||
|
let sku = 'com.habitrpg.ios.habitica.subscription.3month';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies sub key', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingSubscriptionCode'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies receipt existence', async () => {
|
||||||
|
await expect(user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
})).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingReceipt'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let subscribeStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeStub = sinon.stub(applePayments, 'noRenewSubscribe').resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
applePayments.noRenewSubscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
transaction: {receipt: 'receipt'},
|
||||||
|
gift: {
|
||||||
|
uuid: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeStub).to.be.calledOnce;
|
||||||
|
expect(subscribeStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(subscribeStub.args[0][0].sku).to.eql(sku);
|
||||||
|
expect(subscribeStub.args[0][0].receipt).to.eql('receipt');
|
||||||
|
expect(subscribeStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -21,7 +21,7 @@ describe('payments : apple #subscribe', () => {
|
|||||||
let subscribeStub;
|
let subscribeStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
subscribeStub = sinon.stub(applePayments, 'subscribe').returnsPromise().resolves({});
|
subscribeStub = sinon.stub(applePayments, 'subscribe').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {generateUser} from '../../../../../helpers/api-integration/v3';
|
import {generateUser, translate as t} from '../../../../../helpers/api-integration/v3';
|
||||||
import applePayments from '../../../../../../website/server/libs/payments/apple';
|
import applePayments from '../../../../../../website/server/libs/payments/apple';
|
||||||
|
|
||||||
describe('payments : apple #verify', () => {
|
describe('payments : apple #verify', () => {
|
||||||
@@ -9,11 +9,19 @@ describe('payments : apple #verify', () => {
|
|||||||
user = await generateUser();
|
user = await generateUser();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('verifies receipt existence', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingReceipt'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('success', () => {
|
describe('success', () => {
|
||||||
let verifyStub;
|
let verifyStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
verifyStub = sinon.stub(applePayments, 'verifyGemPurchase').returnsPromise().resolves({});
|
verifyStub = sinon.stub(applePayments, 'verifyGemPurchase').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -31,10 +39,31 @@ describe('payments : apple #verify', () => {
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
expect(verifyStub).to.be.calledOnce;
|
expect(verifyStub).to.be.calledOnce;
|
||||||
expect(verifyStub.args[0][0]._id).to.eql(user._id);
|
expect(verifyStub.args[0][0].user._id).to.eql(user._id);
|
||||||
expect(verifyStub.args[0][1]).to.eql('receipt');
|
expect(verifyStub.args[0][0].receipt).to.eql('receipt');
|
||||||
expect(verifyStub.args[0][2]['x-api-key']).to.eql(user.apiToken);
|
expect(verifyStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
expect(verifyStub.args[0][2]['x-api-user']).to.eql(user._id);
|
expect(verifyStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gifts a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
transaction: {
|
||||||
|
receipt: 'receipt',
|
||||||
|
},
|
||||||
|
gift: {
|
||||||
|
uuid: '1',
|
||||||
|
}});
|
||||||
|
|
||||||
|
expect(verifyStub).to.be.calledOnce;
|
||||||
|
expect(verifyStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(verifyStub.args[0][0].receipt).to.eql('receipt');
|
||||||
|
expect(verifyStub.args[0][0].gift.uuid).to.eql('1');
|
||||||
|
expect(verifyStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(verifyStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ describe('payments : google #cancelSubscribe', () => {
|
|||||||
let cancelStub;
|
let cancelStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
cancelStub = sinon.stub(googlePayments, 'cancelSubscribe').returnsPromise().resolves({});
|
cancelStub = sinon.stub(googlePayments, 'cancelSubscribe').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import {generateUser, translate as t} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import googlePayments from '../../../../../../website/server/libs/payments/google';
|
||||||
|
|
||||||
|
describe('payments : google #norenewsubscribe', () => {
|
||||||
|
let endpoint = '/iap/android/norenew-subscribe';
|
||||||
|
let sku = 'com.habitrpg.android.habitica.subscription.3month';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies sub key', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingSubscriptionCode'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies receipt existence', async () => {
|
||||||
|
await expect(user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
})).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingReceipt'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let subscribeStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeStub = sinon.stub(googlePayments, 'noRenewSubscribe').resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
googlePayments.noRenewSubscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
transaction: {
|
||||||
|
receipt: 'receipt',
|
||||||
|
signature: 'signature',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeStub).to.be.calledOnce;
|
||||||
|
expect(subscribeStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(subscribeStub.args[0][0].sku).to.eql(sku);
|
||||||
|
expect(subscribeStub.args[0][0].receipt).to.eql('receipt');
|
||||||
|
expect(subscribeStub.args[0][0].signature).to.eql('signature');
|
||||||
|
expect(subscribeStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gifts a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
transaction: {
|
||||||
|
receipt: 'receipt',
|
||||||
|
signature: 'signature',
|
||||||
|
},
|
||||||
|
gift: {
|
||||||
|
uuid: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeStub).to.be.calledOnce;
|
||||||
|
expect(subscribeStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(subscribeStub.args[0][0].sku).to.eql(sku);
|
||||||
|
expect(subscribeStub.args[0][0].receipt).to.eql('receipt');
|
||||||
|
expect(subscribeStub.args[0][0].signature).to.eql('signature');
|
||||||
|
expect(subscribeStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -21,7 +21,7 @@ describe('payments : google #subscribe', () => {
|
|||||||
let subscribeStub;
|
let subscribeStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
subscribeStub = sinon.stub(googlePayments, 'subscribe').returnsPromise().resolves({});
|
subscribeStub = sinon.stub(googlePayments, 'subscribe').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {generateUser} from '../../../../../helpers/api-integration/v3';
|
import {generateUser, translate as t} from '../../../../../helpers/api-integration/v3';
|
||||||
import googlePayments from '../../../../../../website/server/libs/payments/google';
|
import googlePayments from '../../../../../../website/server/libs/payments/google';
|
||||||
|
|
||||||
describe('payments : google #verify', () => {
|
describe('payments : google #verify', () => {
|
||||||
@@ -9,11 +9,19 @@ describe('payments : google #verify', () => {
|
|||||||
user = await generateUser();
|
user = await generateUser();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('verifies receipt existence', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingReceipt'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('success', () => {
|
describe('success', () => {
|
||||||
let verifyStub;
|
let verifyStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
verifyStub = sinon.stub(googlePayments, 'verifyGemPurchase').returnsPromise().resolves({});
|
verifyStub = sinon.stub(googlePayments, 'verifyGemPurchase').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -30,11 +38,30 @@ describe('payments : google #verify', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(verifyStub).to.be.calledOnce;
|
expect(verifyStub).to.be.calledOnce;
|
||||||
expect(verifyStub.args[0][0]._id).to.eql(user._id);
|
expect(verifyStub.args[0][0].user._id).to.eql(user._id);
|
||||||
expect(verifyStub.args[0][1]).to.eql('receipt');
|
expect(verifyStub.args[0][0].receipt).to.eql('receipt');
|
||||||
expect(verifyStub.args[0][2]).to.eql('signature');
|
expect(verifyStub.args[0][0].signature).to.eql('signature');
|
||||||
expect(verifyStub.args[0][3]['x-api-key']).to.eql(user.apiToken);
|
expect(verifyStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
expect(verifyStub.args[0][3]['x-api-user']).to.eql(user._id);
|
expect(verifyStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gifts a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
transaction: {receipt: 'receipt', signature: 'signature'},
|
||||||
|
gift: {uuid: '1'},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(verifyStub).to.be.calledOnce;
|
||||||
|
expect(verifyStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(verifyStub.args[0][0].receipt).to.eql('receipt');
|
||||||
|
expect(verifyStub.args[0][0].signature).to.eql('signature');
|
||||||
|
expect(verifyStub.args[0][0].gift.uuid).to.eql('1');
|
||||||
|
expect(verifyStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(verifyStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe('payments : paypal #checkout', () => {
|
|||||||
let checkoutStub;
|
let checkoutStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
checkoutStub = sinon.stub(paypalPayments, 'checkout').returnsPromise().resolves('/');
|
checkoutStub = sinon.stub(paypalPayments, 'checkout').resolves('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ describe('payments : paypal #checkoutSuccess', () => {
|
|||||||
let checkoutSuccessStub;
|
let checkoutSuccessStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
checkoutSuccessStub = sinon.stub(paypalPayments, 'checkoutSuccess').returnsPromise().resolves({});
|
checkoutSuccessStub = sinon.stub(paypalPayments, 'checkoutSuccess').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe('payments : paypal #subscribe', () => {
|
|||||||
let subscribeStub;
|
let subscribeStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
subscribeStub = sinon.stub(paypalPayments, 'subscribe').returnsPromise().resolves('/');
|
subscribeStub = sinon.stub(paypalPayments, 'subscribe').resolves('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe('payments : paypal #subscribeCancel', () => {
|
|||||||
let subscribeCancelStub;
|
let subscribeCancelStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
subscribeCancelStub = sinon.stub(paypalPayments, 'subscribeCancel').returnsPromise().resolves('/');
|
subscribeCancelStub = sinon.stub(paypalPayments, 'subscribeCancel').resolves('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ describe('payments : paypal #subscribeSuccess', () => {
|
|||||||
let subscribeSuccessStub;
|
let subscribeSuccessStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
subscribeSuccessStub = sinon.stub(paypalPayments, 'subscribeSuccess').returnsPromise().resolves({});
|
subscribeSuccessStub = sinon.stub(paypalPayments, 'subscribeSuccess').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ describe('payments - paypal - #ipn', () => {
|
|||||||
let ipnStub;
|
let ipnStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
ipnStub = sinon.stub(paypalPayments, 'ipn').returnsPromise().resolves({});
|
ipnStub = sinon.stub(paypalPayments, 'ipn').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user