Compare commits
	
		
			61 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3803ac9197 | |||
| e1621b72ad | |||
| b64a8436e7 | |||
| d8ed9a149f | |||
| 9d7125a311 | |||
| 6d71a3ebf4 | |||
| 75adbf73cf | |||
| e5b8557e4c | |||
| 33d7c94648 | |||
| f6b2ae523d | |||
| 0a500f16cd | |||
| 61da5d8110 | |||
| 773b286216 | |||
| d097eccbd9 | |||
| f15282a3f9 | |||
| 0a8945a294 | |||
| b871e4295d | |||
| 0945060a49 | |||
| f7eae96b8c | |||
| c2a50a1480 | |||
| bb99c2dcd1 | |||
| e8382fb579 | |||
| b5321377bd | |||
| 6e26bbbf5f | |||
| 59e178476e | |||
| 824c109a42 | |||
| f48159b31b | |||
| 6195001d4b | |||
| 0afa80345d | |||
| dbb0d177b8 | |||
| 4ffc06db7b | |||
| 588f3bae89 | |||
| d889432ce8 | |||
| 44830f08bc | |||
| 1cd3ebf8c5 | |||
| 558b69eeaa | |||
| 2b22063a81 | |||
| 48cc380504 | |||
| 75473cabe7 | |||
| 6420ffb055 | |||
| a62ee63c83 | |||
| c89f2a2939 | |||
| d51c58867d | |||
| 2fa520fdde | |||
| 5bb7212420 | |||
| 2226705e3f | |||
| 72932955d1 | |||
| 339e2f39d8 | |||
| 12c6d7e3da | |||
| 1624e666e8 | |||
| 86f4cd00ea | |||
| 518aa3eb08 | |||
| 86985ef735 | |||
| fef7daaf96 | |||
| b14fa05adc | |||
| 7c71e94304 | |||
| 8fa489f2bc | |||
| 512acc0b8c | |||
| 567ac07612 | |||
| fa01864d0d | |||
| 91b25c22ca | 
							
								
								
									
										3
									
								
								.env
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								.env
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
| SSL=false | SSL=true | ||||||
|  | DOMAIN=kauft.es | ||||||
| DISABLE_PROVIDERS=false | DISABLE_PROVIDERS=false | ||||||
| ENABLE_REGISTER=true | ENABLE_REGISTER=true | ||||||
							
								
								
									
										120
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,8 +2,128 @@ | |||||||
|  |  | ||||||
| All notable changes to this project will be documented in this file. Dates are displayed in UTC. | All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||||
|  |  | ||||||
|  | #### [0.6.0](https://git.odit.services/kauft.es/linkylinky/compare/0.5.1...0.6.0) | ||||||
|  |  | ||||||
|  | - Now with custom opengraph (tm) [`9d7125a`](https://git.odit.services/kauft.es/linkylinky/commit/9d7125a31186f3b7f33df4875db12c67cf91f536) | ||||||
|  | - Added rudementary page content [`e1621b7`](https://git.odit.services/kauft.es/linkylinky/commit/e1621b72ade1fce381f30bcf310a6dcf8d1c65ea) | ||||||
|  | - Added migration for disallowing bot previews [`0a500f1`](https://git.odit.services/kauft.es/linkylinky/commit/0a500f16cde0b0e38a115dd4e76185a2a45dda49) | ||||||
|  | - Added basic bot checking [`61da5d8`](https://git.odit.services/kauft.es/linkylinky/commit/61da5d81108a4b86f92e1c05ca99372c6b188347) | ||||||
|  | - Now with working bad bot detection [`75adbf7`](https://git.odit.services/kauft.es/linkylinky/commit/75adbf73cfbf4fadf2cd632ecb687eff95749f52) | ||||||
|  | - New urls can now be created with disabled preview [`33d7c94`](https://git.odit.services/kauft.es/linkylinky/commit/33d7c94648d062ece3fa437e71ce1ded70324cd8) | ||||||
|  | - Added bot check for native short urls [`f6b2ae5`](https://git.odit.services/kauft.es/linkylinky/commit/f6b2ae523da149b72f2be6d9171584cdc0be6e99) | ||||||
|  | - Added package for bot recognition [`773b286`](https://git.odit.services/kauft.es/linkylinky/commit/773b286216c9e530ccdf3fbfcfe95fa938097be5) | ||||||
|  | - Getters now return the no_preview status [`e5b8557`](https://git.odit.services/kauft.es/linkylinky/commit/e5b8557e4ccae90981e675c2adae81236aa9144e) | ||||||
|  | - Added noindex header to all shorturl routes [`0a8945a`](https://git.odit.services/kauft.es/linkylinky/commit/0a8945a294de2bc5bce9410f3ebf20b8f5abd0a5) | ||||||
|  | - Switched docker base images to odit mirror [`d8ed9a1`](https://git.odit.services/kauft.es/linkylinky/commit/d8ed9a149fddae8e8cc61b78cbc940a9d7ade8f2) | ||||||
|  | - Updated opengraph type [`b64a843`](https://git.odit.services/kauft.es/linkylinky/commit/b64a8436e745d176cc49ef72434dce0f8f1bcc12) | ||||||
|  | - Log user agents [`f15282a`](https://git.odit.services/kauft.es/linkylinky/commit/f15282a3f9bdaaf09a36d8662b64a5bc2740633f) | ||||||
|  | - Removed unused log [`6d71a3e`](https://git.odit.services/kauft.es/linkylinky/commit/6d71a3ebf4d880b8291cacd620f86416cff0d744) | ||||||
|  | - removed logging [`d097ecc`](https://git.odit.services/kauft.es/linkylinky/commit/d097eccbd925e3627fa710d7891d269b372d174c) | ||||||
|  |  | ||||||
|  | #### [0.5.1](https://git.odit.services/kauft.es/linkylinky/compare/0.5.0...0.5.1) | ||||||
|  |  | ||||||
|  | > 21 August 2021 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE 0.5.1 [`b871e42`](https://git.odit.services/kauft.es/linkylinky/commit/b871e4295dc4b067f4f4dd28c3f940c8aa9624e0) | ||||||
|  | - Added endpoint to query over all visited urls [`bb99c2d`](https://git.odit.services/kauft.es/linkylinky/commit/bb99c2dcd1ce89af1bc27a035be5265345d2a05f) | ||||||
|  | - Added optional filtering by provider [`0945060`](https://git.odit.services/kauft.es/linkylinky/commit/0945060a49ed35c038df2c04bbd07174bc5654ca) | ||||||
|  | - Shortened return to avoid variable memory asignment [`f7eae96`](https://git.odit.services/kauft.es/linkylinky/commit/f7eae96b8c3479d333fc00bc36bce451733700db) | ||||||
|  | - Changed object property order (just for us pesky humans to improve readability) [`c2a50a1`](https://git.odit.services/kauft.es/linkylinky/commit/c2a50a14807e223987464c63fac6d67ed98b1a93) | ||||||
|  |  | ||||||
|  | #### [0.5.0](https://git.odit.services/kauft.es/linkylinky/compare/0.4.3...0.5.0) | ||||||
|  |  | ||||||
|  | > 21 August 2021 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE 0.5.0 [`e8382fb`](https://git.odit.services/kauft.es/linkylinky/commit/e8382fb579f769364693974cbe74ce06e9810a9a) | ||||||
|  | - Removed visits 404 resolution [`59e1784`](https://git.odit.services/kauft.es/linkylinky/commit/59e178476e8f7e64de92ae23e859b87680e7af64) | ||||||
|  | - Added migration for visits provider [`f48159b`](https://git.odit.services/kauft.es/linkylinky/commit/f48159b31bcaf7c7449c89fb1e3851bcb04f5e3c) | ||||||
|  | - Reverted last change since we can defer it from the provider [`b532137`](https://git.odit.services/kauft.es/linkylinky/commit/b5321377bde9bd7de13e2eee4dd38a072cf0d4a3) | ||||||
|  | - Changed the way visits entrys get compiled to enable provider visits count searches over the default api [`6e26bbb`](https://git.odit.services/kauft.es/linkylinky/commit/6e26bbbf5f29e4c1eaa56c5dc41ab77c192d0cfb) | ||||||
|  | - Server now inserts provider on visit [`824c109`](https://git.odit.services/kauft.es/linkylinky/commit/824c109a420efd0e1e6de01d93827020f3fe5a5f) | ||||||
|  | - Added package script for migration creation [`6195001`](https://git.odit.services/kauft.es/linkylinky/commit/6195001d4b701d39470ff4be0e265f9afb288e78) | ||||||
|  |  | ||||||
|  | #### [0.4.3](https://git.odit.services/kauft.es/linkylinky/compare/0.4.2...0.4.3) | ||||||
|  |  | ||||||
|  | > 21 August 2021 | ||||||
|  |  | ||||||
|  | - Fixed auth error crashing the entire server thanks to fastify handling stuff not the same way that they do in the docs..... [`#1`](https://git.odit.services/kauft.es/linkylinky/issues/1) | ||||||
|  | - 🚀RELEASE 0.4.3 [`0afa803`](https://git.odit.services/kauft.es/linkylinky/commit/0afa80345d47e09e20d4365634f8532248b2044c) | ||||||
|  |  | ||||||
|  | #### [0.4.2](https://git.odit.services/kauft.es/linkylinky/compare/0.4.1...0.4.2) | ||||||
|  |  | ||||||
|  | > 18 August 2021 | ||||||
|  |  | ||||||
|  | - Changed register api route and added user deletion route [`588f3ba`](https://git.odit.services/kauft.es/linkylinky/commit/588f3bae8980f76461d20e15475ec797078b0b54) | ||||||
|  | - 🚀RELEASE 0.4.2 [`4ffc06d`](https://git.odit.services/kauft.es/linkylinky/commit/4ffc06db7bb84bc7bfc9c57a80927f7201185274) | ||||||
|  |  | ||||||
|  | #### [0.4.1](https://git.odit.services/kauft.es/linkylinky/compare/0.4.0...0.4.1) | ||||||
|  |  | ||||||
|  | > 18 August 2021 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE 0.4.1 [`d889432`](https://git.odit.services/kauft.es/linkylinky/commit/d889432ce8a403f6a609423eaf458a5904dc5b98) | ||||||
|  | - Fixed jwtcount not being recognized [`44830f0`](https://git.odit.services/kauft.es/linkylinky/commit/44830f08bc212f8079b5ac2da3d51eedbe6d5c41) | ||||||
|  |  | ||||||
|  | #### [0.4.0](https://git.odit.services/kauft.es/linkylinky/compare/0.3.0...0.4.0) | ||||||
|  |  | ||||||
|  | > 18 August 2021 | ||||||
|  |  | ||||||
|  | - Basic jwt implementation :party: [`75473ca`](https://git.odit.services/kauft.es/linkylinky/commit/75473cabe79975296e473002e16d3abafbd2635e) | ||||||
|  | - Implemented jwtcount basics [`48cc380`](https://git.odit.services/kauft.es/linkylinky/commit/48cc380504206ea08b3a5082f19ad10bdd7cf773) | ||||||
|  | - Implemented jwt count validation and update on logout [`558b69e`](https://git.odit.services/kauft.es/linkylinky/commit/558b69eeaa78ea015473c674d5f919d64128a930) | ||||||
|  | - Switched to fastify-auth to support multiple auth providers [`6420ffb`](https://git.odit.services/kauft.es/linkylinky/commit/6420ffb055f08348c54cd08a193aba5fe5ebc13a) | ||||||
|  | - 🚀RELEASE 0.4.0 [`1cd3ebf`](https://git.odit.services/kauft.es/linkylinky/commit/1cd3ebf8c5a9413b93ab49c8813dad5c5c547cb2) | ||||||
|  | - All authenticated entpoints now accept jwtauth [`2b22063`](https://git.odit.services/kauft.es/linkylinky/commit/2b22063a81193c3d698525a050ef300e542c1f05) | ||||||
|  |  | ||||||
|  | #### [0.3.0](https://git.odit.services/kauft.es/linkylinky/compare/0.2.0...0.3.0) | ||||||
|  |  | ||||||
|  | > 18 August 2021 | ||||||
|  |  | ||||||
|  | - Added license [`5bb7212`](https://git.odit.services/kauft.es/linkylinky/commit/5bb7212420ba102e743d62a47074191cdb264d2a) | ||||||
|  | - 🚀RELEASE 0.3.0 [`a62ee63`](https://git.odit.services/kauft.es/linkylinky/commit/a62ee63c838a64d7fd28ae110cad474e2c531995) | ||||||
|  | - Added stats api route [`c89f2a2`](https://git.odit.services/kauft.es/linkylinky/commit/c89f2a2939b658ffc688646ccce32fc0e1530583) | ||||||
|  | - Added author info [`2fa520f`](https://git.odit.services/kauft.es/linkylinky/commit/2fa520fdde1d55b2766b4b03e394e21a4f6cbae5) | ||||||
|  | - Updated readme [`2226705`](https://git.odit.services/kauft.es/linkylinky/commit/2226705e3f57d7d2f3ef5a79947c3ab44ec62c38) | ||||||
|  | - Added comments [`d51c588`](https://git.odit.services/kauft.es/linkylinky/commit/d51c58867d7508c84f26c236e38567bc6a4adbed) | ||||||
|  |  | ||||||
|  | #### [0.2.0](https://git.odit.services/kauft.es/linkylinky/compare/0.1.4...0.2.0) | ||||||
|  |  | ||||||
|  | > 14 August 2021 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE 0.2.0 [`7293295`](https://git.odit.services/kauft.es/linkylinky/commit/72932955d15976947dd553c5deba51cbf541b215) | ||||||
|  | - Added ebay provider recognition [`12c6d7e`](https://git.odit.services/kauft.es/linkylinky/commit/12c6d7e3da5cb4de6a597b4639f313b8e4319646) | ||||||
|  | - Ebay provider resolution [`339e2f3`](https://git.odit.services/kauft.es/linkylinky/commit/339e2f39d88d42a961e1e495f319dc0663cdc0a6) | ||||||
|  | - Now recognizing with and without protocol [`1624e66`](https://git.odit.services/kauft.es/linkylinky/commit/1624e666e83e0afe346bcacb105ea1a1535f0690) | ||||||
|  |  | ||||||
|  | #### [0.1.4](https://git.odit.services/kauft.es/linkylinky/compare/0.1.3...0.1.4) | ||||||
|  |  | ||||||
|  | > 14 August 2021 | ||||||
|  |  | ||||||
|  | - Added cors [`518aa3e`](https://git.odit.services/kauft.es/linkylinky/commit/518aa3eb08cb72854812130d45b3b89afb074693) | ||||||
|  | - 🚀RELEASE 0.1.4 [`86f4cd0`](https://git.odit.services/kauft.es/linkylinky/commit/86f4cd00ea517f7e2cacbf69f2163eae597610ee) | ||||||
|  |  | ||||||
|  | #### [0.1.3](https://git.odit.services/kauft.es/linkylinky/compare/0.1.2...0.1.3) | ||||||
|  |  | ||||||
|  | > 14 August 2021 | ||||||
|  |  | ||||||
|  | - Weired knex env fix [`fef7daa`](https://git.odit.services/kauft.es/linkylinky/commit/fef7daaf961e9112aa00f2ad22c3b0518ad258a7) | ||||||
|  | - 🚀RELEASE 0.1.3 [`86985ef`](https://git.odit.services/kauft.es/linkylinky/commit/86985ef7355c2db09dcd6c8e52ee7ebde3ed4128) | ||||||
|  |  | ||||||
|  | #### [0.1.2](https://git.odit.services/kauft.es/linkylinky/compare/0.1.1...0.1.2) | ||||||
|  |  | ||||||
|  | > 14 August 2021 | ||||||
|  |  | ||||||
|  | - API Endpoint to get all short urls [`fa01864`](https://git.odit.services/kauft.es/linkylinky/commit/fa01864d0de7921e741d63c3f5795161279ea478) | ||||||
|  | - 🚀RELEASE 0.1.2 [`b14fa05`](https://git.odit.services/kauft.es/linkylinky/commit/b14fa05adc1ef8e34fd73bf5f495505df7d44b33) | ||||||
|  | - Changed the way that the migration get's triggered [`8fa489f`](https://git.odit.services/kauft.es/linkylinky/commit/8fa489f2bcd9d1ad63ab4581b7f3b27eee3d9038) | ||||||
|  | - Get all api endpoints [`91b25c2`](https://git.odit.services/kauft.es/linkylinky/commit/91b25c22ca035aec5cc2fdc80ca4fbb56a2f8b65) | ||||||
|  | - Added optional db volume to docker-compose [`7c71e94`](https://git.odit.services/kauft.es/linkylinky/commit/7c71e943041d8e3ac9dcf95cad27f2f0bc0b024c) | ||||||
|  | - Prod db now resides in db folder [`512acc0`](https://git.odit.services/kauft.es/linkylinky/commit/512acc0b8c15d4cfbafef21ec20707bac4629ea4) | ||||||
|  |  | ||||||
| #### [0.1.1](https://git.odit.services/kauft.es/linkylinky/compare/0.1.0...0.1.1) | #### [0.1.1](https://git.odit.services/kauft.es/linkylinky/compare/0.1.0...0.1.1) | ||||||
|  |  | ||||||
|  | > 14 August 2021 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE 0.1.1 [`55d6b91`](https://git.odit.services/kauft.es/linkylinky/commit/55d6b91cc252ee6676d13df9abd8b61283a07f0f) | ||||||
| - fix: Dockerfile [`807eb9c`](https://git.odit.services/kauft.es/linkylinky/commit/807eb9c267377df0b5f30f81eb380ef8a1c2add2) | - fix: Dockerfile [`807eb9c`](https://git.odit.services/kauft.es/linkylinky/commit/807eb9c267377df0b5f30f81eb380ef8a1c2add2) | ||||||
|  |  | ||||||
| #### [0.1.0](https://git.odit.services/kauft.es/linkylinky/compare/0.0.2...0.1.0) | #### [0.1.0](https://git.odit.services/kauft.es/linkylinky/compare/0.0.2...0.1.0) | ||||||
|   | |||||||
| @@ -1,16 +1,17 @@ | |||||||
| FROM node:16.6.2-alpine3.14 | FROM registry.odit.services/hub/library/node:16.6.2-alpine3.14 | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
| COPY package.json . | COPY package.json . | ||||||
| COPY yarn.lock . | COPY yarn.lock . | ||||||
| RUN yarn --production --frozen-lockfile | RUN yarn --production --frozen-lockfile | ||||||
| COPY migrations ./migrations | COPY migrations ./migrations | ||||||
| COPY src/server.js ./ | COPY src ./src | ||||||
| COPY knexfile.js ./ | COPY knexfile.js ./ | ||||||
|  | RUN mkdir db | ||||||
| #  | #  | ||||||
| # FROM astefanutti/scratch-node:16.0.0 | # FROM astefanutti/scratch-node:16.0.0 | ||||||
| FROM node:16.6.2-alpine3.14 | FROM registry.odit.services/hub/library/node:16.6.2-alpine3.14 | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
| COPY --from=0 /app /app | COPY --from=0 /app /app | ||||||
| ENV NODE_ENV production | ENV NODE_ENV production | ||||||
| EXPOSE 3000 | EXPOSE 3000 | ||||||
| ENTRYPOINT ["node", "./server.js"] | ENTRYPOINT ["/bin/sh", "-c", "yarn migrate && node ./src/server.js"] | ||||||
							
								
								
									
										24
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | MIT License | ||||||
|  | ----------- | ||||||
|  |  | ||||||
|  | Copyright (c) 2021 ODIT.Services (https://odit.services) | ||||||
|  | Permission is hereby granted, free of charge, to any person | ||||||
|  | obtaining a copy of this software and associated documentation | ||||||
|  | files (the "Software"), to deal in the Software without | ||||||
|  | restriction, including without limitation the rights to use, | ||||||
|  | copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the | ||||||
|  | Software is furnished to do so, subject to the following | ||||||
|  | conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be | ||||||
|  | included in all copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||||
|  | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||||||
|  | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||||
|  | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||||||
|  | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||||
|  | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||||
|  | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||||
|  | OTHER DEALINGS IN THE SOFTWARE. | ||||||
| @@ -1,5 +1,8 @@ | |||||||
| # LinkyLinky 🔗 | <p align="center"> | ||||||
| > A small url shortener, originaly developed for kauft.es |   <img height="150" src="https://git.odit.services/user/avatar/kauft.es/140"> | ||||||
|  |   <h1 align="center">LinkyLinky 🔗</h1> | ||||||
|  |   <h3 align="center">A small url shortener, originaly developed for kauft.es</h3> | ||||||
|  | </p> | ||||||
|  |  | ||||||
| ## Dev Setup 🛠 | ## Dev Setup 🛠 | ||||||
| > Runs on port 3000 | > Runs on port 3000 | ||||||
|   | |||||||
| @@ -5,3 +5,5 @@ services: | |||||||
|     #image: registry.odit.services/kauft.es/linkylinky:latest |     #image: registry.odit.services/kauft.es/linkylinky:latest | ||||||
|     ports: |     ports: | ||||||
|       - 3000:3000 |       - 3000:3000 | ||||||
|  |     #volumes: | ||||||
|  |     #  - ./db:/app/db | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ module.exports = { | |||||||
|   production: { |   production: { | ||||||
|     client: 'sqlite3', |     client: 'sqlite3', | ||||||
|     connection: { |     connection: { | ||||||
|       filename: './db.sqlite3' |       filename: './db/db.sqlite3' | ||||||
|     }, |     }, | ||||||
|     migrations: { |     migrations: { | ||||||
|       tableName: 'knex_migrations' |       tableName: 'knex_migrations' | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								migrations/20210818160424_jwtcount.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								migrations/20210818160424_jwtcount.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  |  | ||||||
|  | exports.up = function(knex) { | ||||||
|  |     return knex.schema.table('users', function (table) { | ||||||
|  |         table.integer("jwtcount").defaultTo(0); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | exports.down = function(knex) { | ||||||
|  |    | ||||||
|  | }; | ||||||
							
								
								
									
										10
									
								
								migrations/20210821094219_visits_providers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								migrations/20210821094219_visits_providers.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  |  | ||||||
|  | exports.up = function(knex) { | ||||||
|  |     return knex.schema.table('visits', function (table) { | ||||||
|  |         table.text('provider').defaultTo("N/A"); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | exports.down = function(knex) { | ||||||
|  |    | ||||||
|  | }; | ||||||
							
								
								
									
										10
									
								
								migrations/20210925171533_bot_preview.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								migrations/20210925171533_bot_preview.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  |  | ||||||
|  | exports.up = function(knex) { | ||||||
|  |     return knex.schema.table('urls', function (table) { | ||||||
|  |         table.boolean('no_preview').defaultTo(false); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | exports.down = function(knex) { | ||||||
|  |    | ||||||
|  | }; | ||||||
							
								
								
									
										21
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,20 +1,37 @@ | |||||||
| { | { | ||||||
|   "name": "@odit/shortener-backend", |   "name": "@odit/shortener-backend", | ||||||
|   "version": "0.1.1", |   "version": "0.6.0", | ||||||
|   "main": "index.js", |   "main": "index.js", | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
|   "private": false, |   "private": false, | ||||||
|  |   "author": { | ||||||
|  |     "name": "ODIT.Services", | ||||||
|  |     "email": "info@odit.services", | ||||||
|  |     "url": "https://odit.services" | ||||||
|  |   }, | ||||||
|  |   "contributors": [ | ||||||
|  |     { | ||||||
|  |       "name": "Nicolai Ort", | ||||||
|  |       "email": "info@nicolai-ort.com", | ||||||
|  |       "url": "https://nicolai-ort.com" | ||||||
|  |     } | ||||||
|  |   ], | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "dev": "nodemon src/server.js", |     "dev": "nodemon src/server.js", | ||||||
|     "start": "node src/server.js", |     "start": "node src/server.js", | ||||||
|     "migrate": "knex migrate:latest", |     "migrate": "knex migrate:latest", | ||||||
|     "release": "release-it" |     "release": "release-it", | ||||||
|  |     "create:migration": "knex migrate:make" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "argon2": "^0.28.2", |     "argon2": "^0.28.2", | ||||||
|     "dotenv": "^10.0.0", |     "dotenv": "^10.0.0", | ||||||
|     "fastify": "^3.20.1", |     "fastify": "^3.20.1", | ||||||
|  |     "fastify-auth": "^1.1.0", | ||||||
|     "fastify-basic-auth": "^2.1.0", |     "fastify-basic-auth": "^2.1.0", | ||||||
|  |     "fastify-cors": "^6.0.2", | ||||||
|  |     "fastify-jwt": "^3.0.1", | ||||||
|  |     "isbot": "^3.3.3", | ||||||
|     "knex": "^0.21.21", |     "knex": "^0.21.21", | ||||||
|     "sqlite3": "^5.0.2", |     "sqlite3": "^5.0.2", | ||||||
|     "uniqid": "^5.3.0" |     "uniqid": "^5.3.0" | ||||||
|   | |||||||
							
								
								
									
										241
									
								
								src/server.js
									
									
									
									
									
								
							
							
						
						
									
										241
									
								
								src/server.js
									
									
									
									
									
								
							| @@ -2,12 +2,15 @@ const fastify = require('fastify')({ logger: true }) | |||||||
| var uniqid = require('uniqid'); | var uniqid = require('uniqid'); | ||||||
| require('dotenv').config(); | require('dotenv').config(); | ||||||
| const argon2 = require('argon2'); | const argon2 = require('argon2'); | ||||||
|  | const isBot = require('isbot') | ||||||
|  |  | ||||||
| let config = { | let config = { | ||||||
|     domain: process.env.DOMAIN || "localhost:3000", |     domain: process.env.DOMAIN || "localhost:3000", | ||||||
|     https: (process.env.SSL === 'true') || false, |     https: (process.env.SSL === 'true') || false, | ||||||
|  |     env: process.env.NODE_ENV || 'development', | ||||||
|     recognizeProviders: !(process.env.DISABLE_PROVIDERS === 'true'), |     recognizeProviders: !(process.env.DISABLE_PROVIDERS === 'true'), | ||||||
|     registrationEnabled: (process.env.ENABLE_REGISTER === 'true'), |     registrationEnabled: (process.env.ENABLE_REGISTER === 'true'), | ||||||
|  |     jwt_secret: process.env.JWT_SECRET || "pleaseneverusethisdefaultsecret", | ||||||
|     getBaseUrl() { |     getBaseUrl() { | ||||||
|         if (config.https) { |         if (config.https) { | ||||||
|             return `https://${config.domain}`; |             return `https://${config.domain}`; | ||||||
| @@ -15,29 +18,82 @@ let config = { | |||||||
|         return `http://${config.domain}`; |         return `http://${config.domain}`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | const knexConfiguration = require('../knexfile')[config.env]; | ||||||
| const knex = require('knex')({ | const knex = require('knex')(knexConfiguration); | ||||||
|     client: 'sqlite3', |  | ||||||
|     connection: { |  | ||||||
|         filename: "./dev.sqlite3" |  | ||||||
|     } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| const authenticate = { realm: 'Short' } | const authenticate = { realm: 'Short' } | ||||||
|  | fastify.register(require('fastify-auth')) | ||||||
| fastify.register(require('fastify-basic-auth'), { validate, authenticate }); | fastify.register(require('fastify-basic-auth'), { validate, authenticate }); | ||||||
|  | fastify.register(require('fastify-jwt'), { | ||||||
|  |     secret: config.jwt_secret | ||||||
|  | }); | ||||||
|  | fastify.register(require('fastify-cors'), { | ||||||
|  |     origin: true, | ||||||
|  |     preflight: true, | ||||||
|  |     preflightContinue: true | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | fastify.decorate('verifyJWT', function async(request, reply, done) { | ||||||
|  |     let token = request.headers.authorization; | ||||||
|  |     if (!token || token == "" || token == "Bearer") { | ||||||
|  |         done(new Error("No jwt provided")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (token.startsWith("Bearer")) { | ||||||
|  |         token = token.replace("Bearer ", ""); | ||||||
|  |         fastify.log.info("Detected bearer and replaced it") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fastify.jwt.verify(token, async (err, decoded) => { | ||||||
|  |         if (err) { | ||||||
|  |             fastify.log.error("JWT validation failed:") | ||||||
|  |             done(new Error("JWT Validation failed")); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             if (!decoded.payload) { | ||||||
|  |                 done(new Error("JWT is empty")); | ||||||
|  |             } | ||||||
|  |             fastify.log.info(`Token verified. User is ${decoded.payload.user}`); | ||||||
|  |  | ||||||
|  |             const jwtcount = (await knex.select('jwtcount') | ||||||
|  |                 .from('users') | ||||||
|  |                 .where('username', '=', decoded.payload.user) | ||||||
|  |                 .limit(1))[0].jwtcount; | ||||||
|  |  | ||||||
|  |             if (decoded.payload.jwtcount < jwtcount) { | ||||||
|  |                 fastify.log.error("Auth ended at jwtcount") | ||||||
|  |                 done(new Error("JWT in no longer valid")) | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 fastify.log.info(`JWT count verified`); | ||||||
|  |                 request.user = decoded.payload.user; | ||||||
|  |                 done() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }) | ||||||
|  | }) | ||||||
|  |  | ||||||
| //Automagic Amazn redirects on /a/ | //Automagic Amazn redirects on /a/ | ||||||
| fastify.get('/a/:id', async (req, res) => { | fastify.get('/a/:id', async (req, res) => { | ||||||
|     res.redirect(302, `https://amazon.de/dp/${req.params.id}`) |     res.redirect(302, `https://amazon.de/dp/${req.params.id}`) | ||||||
|  |     await knex('visits').insert({ shortcode: req.params.id, provider: 'a' }); | ||||||
| }) | }) | ||||||
|  |  | ||||||
| //Automagic Youtube redirects on /yt/ | //Automagic Youtube redirects on /yt/ | ||||||
| fastify.get('/yt/:id', async (req, res) => { | fastify.get('/yt/:id', async (req, res) => { | ||||||
|     res.redirect(302, `https://youtu.be/${req.params.id}`) |     res.redirect(302, `https://youtu.be/${req.params.id}`) | ||||||
|  |     await knex('visits').insert({ shortcode: req.params.id, provider: 'yt' }); | ||||||
| }) | }) | ||||||
| //Automagic Youtube Playlist redirects on /ytpl/ | //Automagic Youtube Playlist redirects on /ytpl/ | ||||||
| fastify.get('/ytpl/:id', async (req, res) => { | fastify.get('/ytpl/:id', async (req, res) => { | ||||||
|     res.redirect(302, `https://youtube.com/playlist?list=${req.params.id}`) |     res.redirect(302, `https://youtube.com/playlist?list=${req.params.id}`) | ||||||
|  |     await knex('visits').insert({ shortcode: req.params.id, provider: 'ytpl' }); | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | //Automagic ebay item redirects on /e/ | ||||||
|  | fastify.get('/e/:id', async (req, res) => { | ||||||
|  |     res.redirect(302, `https://ebay.de/itm/${req.params.id}`) | ||||||
|  |     await knex('visits').insert({ shortcode: req.params.id, provider: 'e' }); | ||||||
| }) | }) | ||||||
|  |  | ||||||
| //Normal shorturls | //Normal shorturls | ||||||
| @@ -48,15 +104,46 @@ fastify.get('/:shortcode', async (req, res) => { | |||||||
|     if (!shortcode) { |     if (!shortcode) { | ||||||
|         return 404; |         return 404; | ||||||
|     } |     } | ||||||
|     const target = await knex.select('target') |     const target = await knex.select('target', 'no_preview') | ||||||
|         .from('urls') |         .from('urls') | ||||||
|         .where('shortcode', '=', shortcode) |         .where('shortcode', '=', shortcode) | ||||||
|         .limit(1); |         .limit(1); | ||||||
|     if (!target[0]) { |     if (!target[0]) { | ||||||
|         return 404 |         return 404 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (isBot(req.headers['user-agent']) && target[0].no_preview) { | ||||||
|  |         return ` | ||||||
|  |         <!DOCTYPE html> | ||||||
|  |         <html lang="en"> | ||||||
|  |         <head> | ||||||
|  |             <meta charset="UTF-8"> | ||||||
|  |             <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||||
|  |             <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|  |             <meta property="og:title" content="LinkyLinky"> | ||||||
|  |             <meta property="og:site_name" content="LinkyLinky by Kauft.es"> | ||||||
|  |             <meta property="og:url" content="https://kauft.es/"> | ||||||
|  |             <meta property="og:description" content="LinkyLinky by Kauft.es is a custom url shortener. You're reading this, b/c someone doesn't want their shorturl to be indexed by bots/crawlers/spiders."> | ||||||
|  |             <meta property="og:type" content="article"> | ||||||
|  |             <meta property="og:image" content="https://kauft.es/dashboard/icon_128.png"> | ||||||
|  |  | ||||||
|  |             <title>LinkyLinky</title> | ||||||
|  |         </head> | ||||||
|  |         <body> | ||||||
|  |         <p align="center"> | ||||||
|  |         <img height="150" src="https://kauft.es/dashboard/icon_128.png"> | ||||||
|  |         <h1 align="center">LinkyLinky 🔗</h1> | ||||||
|  |         <h3 align="center">A small url shortener, originaly developed for kauft.es</h3> | ||||||
|  |         <p>LinkyLinky by Kauft.es is a custom url shortener.<br> | ||||||
|  |         You're reading this, b/c someone doesn't want their shorturl to be indexed by bots/crawlers/spiders.</p> | ||||||
|  |         </p>         | ||||||
|  |         </body> | ||||||
|  |         </html> | ||||||
|  |         `; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     res.redirect(302, target[0].target); |     res.redirect(302, target[0].target); | ||||||
|     await knex('visits').insert({ shortcode }); |     await knex('visits').insert({ shortcode, provider: 'native' }); | ||||||
| }) | }) | ||||||
|  |  | ||||||
| //Create new url schema | //Create new url schema | ||||||
| @@ -66,6 +153,7 @@ const newUrlSchema = { | |||||||
|         properties: { |         properties: { | ||||||
|             target: { type: 'string' }, |             target: { type: 'string' }, | ||||||
|             shortcode: { type: 'string' }, |             shortcode: { type: 'string' }, | ||||||
|  |             no_preview: { type: 'boolean' }, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| @@ -74,6 +162,7 @@ const newUrlSchema = { | |||||||
| fastify.post('/api', { newUrlSchema }, async (req, res) => { | fastify.post('/api', { newUrlSchema }, async (req, res) => { | ||||||
|     const target = req.body?.target; |     const target = req.body?.target; | ||||||
|     let shortcode = req.body?.shortcode; |     let shortcode = req.body?.shortcode; | ||||||
|  |     let no_preview = req.body?.no_preview || false; | ||||||
|  |  | ||||||
|     //Check if the user provided a target |     //Check if the user provided a target | ||||||
|     if (!target) { |     if (!target) { | ||||||
| @@ -93,7 +182,7 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => { | |||||||
|                 return response; |                 return response; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         const exists = await knex.select('shortcode') |         const exists = await knex.select('shortcode', 'no_preview') | ||||||
|             .from('urls') |             .from('urls') | ||||||
|             .where('target', '=', target) |             .where('target', '=', target) | ||||||
|             .limit(1); |             .limit(1); | ||||||
| @@ -102,7 +191,8 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => { | |||||||
|             return { |             return { | ||||||
|                 url: `${config.getBaseUrl()}/${shortcode}`, |                 url: `${config.getBaseUrl()}/${shortcode}`, | ||||||
|                 shortcode, |                 shortcode, | ||||||
|                 target |                 target, | ||||||
|  |                 no_preview: exists[0].no_preview | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         shortcode = uniqid(); |         shortcode = uniqid(); | ||||||
| @@ -124,12 +214,27 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     //Create a new db entry |     //Create a new db entry | ||||||
|     await knex('urls').insert({ target, shortcode }); |     await knex('urls').insert({ target, shortcode, no_preview }); | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|         url: `${config.getBaseUrl()}/${shortcode}`, |         url: `${config.getBaseUrl()}/${shortcode}`, | ||||||
|         shortcode, |         shortcode, | ||||||
|         target |         target, | ||||||
|  |         no_preview | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | //Get stats api route | ||||||
|  | fastify.get('/api/stats', async (req, res) => { | ||||||
|  |     const urls = await knex.select('shortcode') | ||||||
|  |         .from('urls'); | ||||||
|  |  | ||||||
|  |     const visits = await knex.select('timestamp') | ||||||
|  |         .from('visits'); | ||||||
|  |  | ||||||
|  |     return { | ||||||
|  |         urls: urls.length, | ||||||
|  |         visits: visits.length, | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
| @@ -142,7 +247,7 @@ fastify.get('/api/:shortcode', async (req, res) => { | |||||||
|         return 404; |         return 404; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const exists = await knex.select('shortcode', 'target') |     const exists = await knex.select('shortcode', 'target', 'no_preview') | ||||||
|         .from('urls') |         .from('urls') | ||||||
|         .where('shortcode', '=', shortcode) |         .where('shortcode', '=', shortcode) | ||||||
|         .limit(1); |         .limit(1); | ||||||
| @@ -158,12 +263,14 @@ fastify.get('/api/:shortcode', async (req, res) => { | |||||||
|         url: `${config.getBaseUrl()}/${exists[0].shortcode}`, |         url: `${config.getBaseUrl()}/${exists[0].shortcode}`, | ||||||
|         shortcode: exists[0].shortcode, |         shortcode: exists[0].shortcode, | ||||||
|         target: exists[0].target, |         target: exists[0].target, | ||||||
|  |         no_preview: exists[0].no_preview, | ||||||
|         visits: visits.length |         visits: visits.length | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  |  | ||||||
| //User registration | //User registration | ||||||
| fastify.post('/api/register', async (req, res) => { | fastify.post('/api/auth/register', async (req, res) => { | ||||||
|     if (!config.registrationEnabled) { |     if (!config.registrationEnabled) { | ||||||
|         res.statusCode = 400; |         res.statusCode = 400; | ||||||
|         return "Registration was disabled by your admin"; |         return "Registration was disabled by your admin"; | ||||||
| @@ -195,9 +302,10 @@ fastify.post('/api/register', async (req, res) => { | |||||||
|     return "Done!" |     return "Done!" | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | //Anything in here has some kind of auth | ||||||
| fastify.after(() => { | fastify.after(() => { | ||||||
|     //Get url api route |     //Get url visits api route | ||||||
|     fastify.get('/api/:shortcode/visits', { onRequest: fastify.basicAuth }, async (req, res) => { |     fastify.get('/api/:shortcode/visits', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => { | ||||||
|         const shortcode = req.params.shortcode; |         const shortcode = req.params.shortcode; | ||||||
|  |  | ||||||
|         //This should never happen but better safe than 500 |         //This should never happen but better safe than 500 | ||||||
| @@ -205,23 +313,26 @@ fastify.after(() => { | |||||||
|             return 404; |             return 404; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const exists = await knex.select('shortcode', 'target') |         const visits = await knex.select('timestamp', 'provider') | ||||||
|             .from('urls') |  | ||||||
|             .where('shortcode', '=', shortcode) |  | ||||||
|             .limit(1); |  | ||||||
|         if (exists.length == 0) { |  | ||||||
|             return 404; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         const visits = await knex.select('timestamp') |  | ||||||
|             .from('visits') |             .from('visits') | ||||||
|             .where('shortcode', '=', shortcode); |             .where('shortcode', '=', shortcode); | ||||||
|  |  | ||||||
|         return visits; |         return visits; | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     //Get all visits api route | ||||||
|  |     fastify.get('/api/visits', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => { | ||||||
|  |         if (req.query.provider) { | ||||||
|  |             return await knex.select('shortcode', 'provider', 'timestamp') | ||||||
|  |                 .from('visits') | ||||||
|  |                 .where("provider", "=", req.query.provider); | ||||||
|  |         } | ||||||
|  |         return await knex.select('shortcode', 'provider', 'timestamp') | ||||||
|  |             .from('visits'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     //Get url api route |     //Get url api route | ||||||
|     fastify.delete('/api/:shortcode', async (req, res) => { |     fastify.delete('/api/:shortcode', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => { | ||||||
|         const shortcode = req.params.shortcode; |         const shortcode = req.params.shortcode; | ||||||
|  |  | ||||||
|         //This should never happen but better safe than 500 |         //This should never happen but better safe than 500 | ||||||
| @@ -237,6 +348,63 @@ fastify.after(() => { | |||||||
|         return true; |         return true; | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     //Get all urls api route | ||||||
|  |     fastify.get('/api', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => { | ||||||
|  |         urls = await knex.select('target', 'shortcode', 'no_preview') | ||||||
|  |             .from('urls'); | ||||||
|  |  | ||||||
|  |         for (let url of urls) { | ||||||
|  |             url.url = `${config.getBaseUrl()}/${url.shortcode}` | ||||||
|  |             if (req.query.showVisits) { | ||||||
|  |                 url.visits = (await knex.select('timestamp') | ||||||
|  |                     .from('visits') | ||||||
|  |                     .where('shortcode', '=', url.shortcode)).length; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return urls; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     fastify.post('/api/auth/login', { onRequest: fastify.auth([fastify.basicAuth]) }, async (req, reply) => { | ||||||
|  |         const jwtcount = (await knex.select('jwtcount') | ||||||
|  |             .from('users') | ||||||
|  |             .where('username', '=', req.user) | ||||||
|  |             .limit(1))[0].jwtcount; | ||||||
|  |         const payload = { | ||||||
|  |             user: req.user, | ||||||
|  |             jwtcount | ||||||
|  |         }; | ||||||
|  |         const token = fastify.jwt.sign({ payload }) | ||||||
|  |         reply.send({ token }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     fastify.post('/api/auth/check', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, (req, reply) => { | ||||||
|  |         return "logged in"; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     fastify.post('/api/auth/logout', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, reply) => { | ||||||
|  |         let jwtcount = (await knex.select('jwtcount') | ||||||
|  |             .from('users') | ||||||
|  |             .where('username', '=', req.user) | ||||||
|  |             .limit(1))[0].jwtcount; | ||||||
|  |         jwtcount += 1; | ||||||
|  |         await knex('users') | ||||||
|  |             .where('username', '=', req.user) | ||||||
|  |             .update({ | ||||||
|  |                 jwtcount | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |         return "Done!"; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     fastify.post('/api/auth/deleteme', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, reply) => { | ||||||
|  |         await knex('users') | ||||||
|  |             .where('username', '=', req.user) | ||||||
|  |             .delete(); | ||||||
|  |  | ||||||
|  |         return "Done!"; | ||||||
|  |     }); | ||||||
|  |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -266,7 +434,7 @@ function checkKnownProviders(target) { | |||||||
|             target |             target | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     const amazonID = target.match(/https?:\/\/(www|smile|)\.?(amazon|smile)\.(de)(?:(?:\/.*\/|\/)(?:dp|gp))(\/product\/|\/)([A-Z0-9]+)/); |     const amazonID = target.match(/(?:https?:\/\/|)(www|smile|)\.?(amazon|smile)\.(de)(?:(?:\/.*\/|\/)(?:dp|gp))(\/product\/|\/)([A-Z0-9]+)/); | ||||||
|     if (amazonID) { |     if (amazonID) { | ||||||
|         const shortcode = `a/${amazonID[5]}` |         const shortcode = `a/${amazonID[5]}` | ||||||
|         return { |         return { | ||||||
| @@ -275,6 +443,15 @@ function checkKnownProviders(target) { | |||||||
|             target |             target | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     const ebayID = target.match(/(?:[ebay]*(?:[\/]|[itm=])|^)([0-9]{9,12})/); | ||||||
|  |     if (ebayID) { | ||||||
|  |         const shortcode = `e/${ebayID[1]}` | ||||||
|  |         return { | ||||||
|  |             url: `${config.getBaseUrl()}/${shortcode}`, | ||||||
|  |             shortcode, | ||||||
|  |             target | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     return null; |     return null; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -294,17 +471,11 @@ async function validate(username, password, req, reply) { | |||||||
|     if (!(await argon2.verify(user[0].password, password))) { |     if (!(await argon2.verify(user[0].password, password))) { | ||||||
|         return new Error('Wrong credentials'); |         return new Error('Wrong credentials'); | ||||||
|     } |     } | ||||||
|  |     req.user = username; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Run the server! | // Run the server! | ||||||
| const start = async () => { | const start = async () => { | ||||||
|     try { |  | ||||||
|         await knex.migrate.latest() |  | ||||||
|     } catch (err) { |  | ||||||
|         fastify.log.error(err) |  | ||||||
|         process.exit(1) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|         await fastify.listen(3000, '0.0.0.0') |         await fastify.listen(3000, '0.0.0.0') | ||||||
|     } catch (err) { |     } catch (err) { | ||||||
|   | |||||||
							
								
								
									
										171
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -216,6 +216,13 @@ | |||||||
|   resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" |   resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" | ||||||
|   integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== |   integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== | ||||||
|  |  | ||||||
|  | "@types/jsonwebtoken@^8.5.0": | ||||||
|  |   version "8.5.4" | ||||||
|  |   resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz#50ccaf0aa6f5d7b9956e70fe323b76e582991913" | ||||||
|  |   integrity sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg== | ||||||
|  |   dependencies: | ||||||
|  |     "@types/node" "*" | ||||||
|  |  | ||||||
| "@types/keyv@*": | "@types/keyv@*": | ||||||
|   version "3.1.2" |   version "3.1.2" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.2.tgz#5d97bb65526c20b6e0845f6b0d2ade4f28604ee5" |   resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.2.tgz#5d97bb65526c20b6e0845f6b0d2ade4f28604ee5" | ||||||
| @@ -567,6 +574,11 @@ braces@^3.0.1, braces@~3.0.2: | |||||||
|   dependencies: |   dependencies: | ||||||
|     fill-range "^7.0.1" |     fill-range "^7.0.1" | ||||||
|  |  | ||||||
|  | buffer-equal-constant-time@1.0.1: | ||||||
|  |   version "1.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" | ||||||
|  |   integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= | ||||||
|  |  | ||||||
| buffer@^5.5.0: | buffer@^5.5.0: | ||||||
|   version "5.7.1" |   version "5.7.1" | ||||||
|   resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" |   resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" | ||||||
| @@ -1052,6 +1064,13 @@ ecc-jsbn@~0.1.1: | |||||||
|     jsbn "~0.1.0" |     jsbn "~0.1.0" | ||||||
|     safer-buffer "^2.1.0" |     safer-buffer "^2.1.0" | ||||||
|  |  | ||||||
|  | ecdsa-sig-formatter@1.0.11: | ||||||
|  |   version "1.0.11" | ||||||
|  |   resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" | ||||||
|  |   integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== | ||||||
|  |   dependencies: | ||||||
|  |     safe-buffer "^5.0.1" | ||||||
|  |  | ||||||
| emoji-regex@^7.0.1: | emoji-regex@^7.0.1: | ||||||
|   version "7.0.3" |   version "7.0.3" | ||||||
|   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" |   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" | ||||||
| @@ -1240,6 +1259,21 @@ fast-safe-stringify@^2.0.8: | |||||||
|   resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f" |   resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f" | ||||||
|   integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag== |   integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag== | ||||||
|  |  | ||||||
|  | fastfall@^1.5.0: | ||||||
|  |   version "1.5.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/fastfall/-/fastfall-1.5.1.tgz#3fee03331a49d1d39b3cdf7a5e9cd66f475e7b94" | ||||||
|  |   integrity sha1-P+4DMxpJ0dObPN96XpzWb0dee5Q= | ||||||
|  |   dependencies: | ||||||
|  |     reusify "^1.0.0" | ||||||
|  |  | ||||||
|  | fastify-auth@^1.1.0: | ||||||
|  |   version "1.1.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/fastify-auth/-/fastify-auth-1.1.0.tgz#75076c9c0664addaff07078907db6432086be1d6" | ||||||
|  |   integrity sha512-8IajmAZB3QJ3wTP0q8Z3TG9DkxrIcAlS85TdPCBEfJi3mMKQd/sCYxtZ0dYv11v5hZaJ9z8XmNzhK3AH6/JpNw== | ||||||
|  |   dependencies: | ||||||
|  |     fastify-plugin "^3.0.0" | ||||||
|  |     reusify "^1.0.4" | ||||||
|  |  | ||||||
| fastify-basic-auth@^2.1.0: | fastify-basic-auth@^2.1.0: | ||||||
|   version "2.1.0" |   version "2.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/fastify-basic-auth/-/fastify-basic-auth-2.1.0.tgz#a368e4e900f402a2c26f4cab927484b9f2ac539c" |   resolved "https://registry.yarnpkg.com/fastify-basic-auth/-/fastify-basic-auth-2.1.0.tgz#a368e4e900f402a2c26f4cab927484b9f2ac539c" | ||||||
| @@ -1249,11 +1283,30 @@ fastify-basic-auth@^2.1.0: | |||||||
|     fastify-plugin "^3.0.0" |     fastify-plugin "^3.0.0" | ||||||
|     http-errors "^1.7.3" |     http-errors "^1.7.3" | ||||||
|  |  | ||||||
|  | fastify-cors@^6.0.2: | ||||||
|  |   version "6.0.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/fastify-cors/-/fastify-cors-6.0.2.tgz#4fd5102549659e9b34d252fd7ee607b63d021390" | ||||||
|  |   integrity sha512-sE0AOyzmj5hLLRRVgenjA6G2iOGX35/1S3QGYB9rr9TXelMZB3lFrXy4CzwYVOMiujJeMiLgO4J7eRm8sQSv8Q== | ||||||
|  |   dependencies: | ||||||
|  |     fastify-plugin "^3.0.0" | ||||||
|  |     vary "^1.1.2" | ||||||
|  |  | ||||||
| fastify-error@^0.3.0: | fastify-error@^0.3.0: | ||||||
|   version "0.3.1" |   version "0.3.1" | ||||||
|   resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" |   resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" | ||||||
|   integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== |   integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== | ||||||
|  |  | ||||||
|  | fastify-jwt@^3.0.1: | ||||||
|  |   version "3.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/fastify-jwt/-/fastify-jwt-3.0.1.tgz#aaec719c7f103eb9fb648fda22690e3cec7911d4" | ||||||
|  |   integrity sha512-p6/7QSa9rdO/m4zCcq1oge63qXkfPsrdfPwVkay9HAGD4rh0UuntB/MeWLy+1ZHNay5foATvFB3A9nG15S7RsA== | ||||||
|  |   dependencies: | ||||||
|  |     "@types/jsonwebtoken" "^8.5.0" | ||||||
|  |     fastify-plugin "^3.0.0" | ||||||
|  |     http-errors "^1.8.0" | ||||||
|  |     jsonwebtoken "^8.5.1" | ||||||
|  |     steed "^1.1.3" | ||||||
|  |  | ||||||
| fastify-plugin@^3.0.0: | fastify-plugin@^3.0.0: | ||||||
|   version "3.0.0" |   version "3.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.0.tgz#cf1b8c8098e3b5a7c8c30e6aeb06903370c054ca" |   resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.0.tgz#cf1b8c8098e3b5a7c8c30e6aeb06903370c054ca" | ||||||
| @@ -1286,13 +1339,29 @@ fastify@^3.20.1: | |||||||
|     semver "^7.3.2" |     semver "^7.3.2" | ||||||
|     tiny-lru "^7.0.0" |     tiny-lru "^7.0.0" | ||||||
|  |  | ||||||
| fastq@^1.6.0, fastq@^1.6.1: | fastparallel@^2.2.0: | ||||||
|  |   version "2.4.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/fastparallel/-/fastparallel-2.4.0.tgz#65fbec1a5e5902494be772cf5765cbaaece08688" | ||||||
|  |   integrity sha512-sacwQ7wwKlQXsa7TN24UvMBLZNLmVcPhmxccC9riFqb3N+fSczJL8eWdnZodZ/KijGVgNBBfvF/NeXER08uXnQ== | ||||||
|  |   dependencies: | ||||||
|  |     reusify "^1.0.4" | ||||||
|  |     xtend "^4.0.2" | ||||||
|  |  | ||||||
|  | fastq@^1.3.0, fastq@^1.6.0, fastq@^1.6.1: | ||||||
|   version "1.11.1" |   version "1.11.1" | ||||||
|   resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" |   resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" | ||||||
|   integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw== |   integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     reusify "^1.0.4" |     reusify "^1.0.4" | ||||||
|  |  | ||||||
|  | fastseries@^1.7.0: | ||||||
|  |   version "1.7.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/fastseries/-/fastseries-1.7.2.tgz#d22ce13b9433dff3388d91dbd6b8bda9b21a0f4b" | ||||||
|  |   integrity sha1-0izhO5Qz3/M4jZHb1ri9qbIaD0s= | ||||||
|  |   dependencies: | ||||||
|  |     reusify "^1.0.0" | ||||||
|  |     xtend "^4.0.0" | ||||||
|  |  | ||||||
| figures@^3.0.0: | figures@^3.0.0: | ||||||
|   version "3.2.0" |   version "3.2.0" | ||||||
|   resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" |   resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" | ||||||
| @@ -1728,7 +1797,7 @@ http-cache-semantics@^4.0.0: | |||||||
|   resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" |   resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" | ||||||
|   integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== |   integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== | ||||||
|  |  | ||||||
| http-errors@^1.7.3: | http-errors@^1.7.3, http-errors@^1.8.0: | ||||||
|   version "1.8.0" |   version "1.8.0" | ||||||
|   resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" |   resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" | ||||||
|   integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== |   integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== | ||||||
| @@ -2159,6 +2228,11 @@ isarray@1.0.0, isarray@~1.0.0: | |||||||
|   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" |   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" | ||||||
|   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= |   integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= | ||||||
|  |  | ||||||
|  | isbot@^3.3.3: | ||||||
|  |   version "3.3.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.3.3.tgz#6a2124a6c1dda5db2d0060c4e292b346ecbd2249" | ||||||
|  |   integrity sha512-a3HFPPsvtLroqpuTHHJTaUpPHUO0vjPbptJDzJYkymRvOI8tugWM6zE2oq22w5VOq4A5hrX+YRS7VdIPAgWLfw== | ||||||
|  |  | ||||||
| isexe@^2.0.0: | isexe@^2.0.0: | ||||||
|   version "2.0.0" |   version "2.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" |   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" | ||||||
| @@ -2221,6 +2295,22 @@ json-stringify-safe@~5.0.1: | |||||||
|   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" |   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" | ||||||
|   integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= |   integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= | ||||||
|  |  | ||||||
|  | jsonwebtoken@^8.5.1: | ||||||
|  |   version "8.5.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" | ||||||
|  |   integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== | ||||||
|  |   dependencies: | ||||||
|  |     jws "^3.2.2" | ||||||
|  |     lodash.includes "^4.3.0" | ||||||
|  |     lodash.isboolean "^3.0.3" | ||||||
|  |     lodash.isinteger "^4.0.4" | ||||||
|  |     lodash.isnumber "^3.0.3" | ||||||
|  |     lodash.isplainobject "^4.0.6" | ||||||
|  |     lodash.isstring "^4.0.1" | ||||||
|  |     lodash.once "^4.0.0" | ||||||
|  |     ms "^2.1.1" | ||||||
|  |     semver "^5.6.0" | ||||||
|  |  | ||||||
| jsprim@^1.2.2: | jsprim@^1.2.2: | ||||||
|   version "1.4.1" |   version "1.4.1" | ||||||
|   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" |   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" | ||||||
| @@ -2231,6 +2321,23 @@ jsprim@^1.2.2: | |||||||
|     json-schema "0.2.3" |     json-schema "0.2.3" | ||||||
|     verror "1.10.0" |     verror "1.10.0" | ||||||
|  |  | ||||||
|  | jwa@^1.4.1: | ||||||
|  |   version "1.4.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" | ||||||
|  |   integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== | ||||||
|  |   dependencies: | ||||||
|  |     buffer-equal-constant-time "1.0.1" | ||||||
|  |     ecdsa-sig-formatter "1.0.11" | ||||||
|  |     safe-buffer "^5.0.1" | ||||||
|  |  | ||||||
|  | jws@^3.2.2: | ||||||
|  |   version "3.2.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" | ||||||
|  |   integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== | ||||||
|  |   dependencies: | ||||||
|  |     jwa "^1.4.1" | ||||||
|  |     safe-buffer "^5.0.1" | ||||||
|  |  | ||||||
| keyv@^3.0.0: | keyv@^3.0.0: | ||||||
|   version "3.1.0" |   version "3.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" |   resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" | ||||||
| @@ -2331,6 +2438,41 @@ locate-path@^6.0.0: | |||||||
|   dependencies: |   dependencies: | ||||||
|     p-locate "^5.0.0" |     p-locate "^5.0.0" | ||||||
|  |  | ||||||
|  | lodash.includes@^4.3.0: | ||||||
|  |   version "4.3.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" | ||||||
|  |   integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= | ||||||
|  |  | ||||||
|  | lodash.isboolean@^3.0.3: | ||||||
|  |   version "3.0.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" | ||||||
|  |   integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= | ||||||
|  |  | ||||||
|  | lodash.isinteger@^4.0.4: | ||||||
|  |   version "4.0.4" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" | ||||||
|  |   integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= | ||||||
|  |  | ||||||
|  | lodash.isnumber@^3.0.3: | ||||||
|  |   version "3.0.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" | ||||||
|  |   integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= | ||||||
|  |  | ||||||
|  | lodash.isplainobject@^4.0.6: | ||||||
|  |   version "4.0.6" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" | ||||||
|  |   integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= | ||||||
|  |  | ||||||
|  | lodash.isstring@^4.0.1: | ||||||
|  |   version "4.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" | ||||||
|  |   integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= | ||||||
|  |  | ||||||
|  | lodash.once@^4.0.0: | ||||||
|  |   version "4.1.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" | ||||||
|  |   integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= | ||||||
|  |  | ||||||
| lodash@4.17.21, lodash@^4.17.20, lodash@^4.17.21: | lodash@4.17.21, lodash@^4.17.20, lodash@^4.17.21: | ||||||
|   version "4.17.21" |   version "4.17.21" | ||||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" |   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" | ||||||
| @@ -3309,7 +3451,7 @@ retry@0.12.0: | |||||||
|   resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" |   resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" | ||||||
|   integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= |   integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= | ||||||
|  |  | ||||||
| reusify@^1.0.4: | reusify@^1.0.0, reusify@^1.0.4: | ||||||
|   version "1.0.4" |   version "1.0.4" | ||||||
|   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" |   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" | ||||||
|   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== |   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== | ||||||
| @@ -3410,7 +3552,7 @@ semver@7.3.5, semver@^7.3.2, semver@^7.3.4: | |||||||
|   dependencies: |   dependencies: | ||||||
|     lru-cache "^6.0.0" |     lru-cache "^6.0.0" | ||||||
|  |  | ||||||
| semver@^5.3.0, semver@^5.7.1: | semver@^5.3.0, semver@^5.6.0, semver@^5.7.1: | ||||||
|   version "5.7.1" |   version "5.7.1" | ||||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" |   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" | ||||||
|   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== |   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== | ||||||
| @@ -3599,6 +3741,17 @@ static-extend@^0.1.1: | |||||||
|   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" |   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" | ||||||
|   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= |   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= | ||||||
|  |  | ||||||
|  | steed@^1.1.3: | ||||||
|  |   version "1.1.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/steed/-/steed-1.1.3.tgz#f1525dd5adb12eb21bf74749537668d625b9abc5" | ||||||
|  |   integrity sha1-8VJd1a2xLrIb90dJU3Zo1iW5q8U= | ||||||
|  |   dependencies: | ||||||
|  |     fastfall "^1.5.0" | ||||||
|  |     fastparallel "^2.2.0" | ||||||
|  |     fastq "^1.3.0" | ||||||
|  |     fastseries "^1.7.0" | ||||||
|  |     reusify "^1.0.0" | ||||||
|  |  | ||||||
| strict-uri-encode@^2.0.0: | strict-uri-encode@^2.0.0: | ||||||
|   version "2.0.0" |   version "2.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" |   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" | ||||||
| @@ -4014,6 +4167,11 @@ v8flags@^3.2.0: | |||||||
|   dependencies: |   dependencies: | ||||||
|     homedir-polyfill "^1.0.1" |     homedir-polyfill "^1.0.1" | ||||||
|  |  | ||||||
|  | vary@^1.1.2: | ||||||
|  |   version "1.1.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" | ||||||
|  |   integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= | ||||||
|  |  | ||||||
| verror@1.10.0: | verror@1.10.0: | ||||||
|   version "1.10.0" |   version "1.10.0" | ||||||
|   resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" |   resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" | ||||||
| @@ -4094,6 +4252,11 @@ xdg-basedir@^4.0.0: | |||||||
|   resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" |   resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" | ||||||
|   integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== |   integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== | ||||||
|  |  | ||||||
|  | xtend@^4.0.0, xtend@^4.0.2: | ||||||
|  |   version "4.0.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" | ||||||
|  |   integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== | ||||||
|  |  | ||||||
| yallist@^3.0.0, yallist@^3.1.1: | yallist@^3.0.0, yallist@^3.1.1: | ||||||
|   version "3.1.1" |   version "3.1.1" | ||||||
|   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" |   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user