Merge branch 'master' of https://github.com/fosscord/fosscord-api
This commit is contained in:
		
						commit
						b00815b025
					
				
							
								
								
									
										4
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| MONGO_URL=mongodb://localhost/fosscord | ||||
| PORT=3001 | ||||
| PRODUCTION=TRUE | ||||
| THREADS=# automatically use all available cores, only available if production = true | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -105,3 +105,7 @@ dist | ||||
| 
 | ||||
| .DS_STORE | ||||
| src/ready.json | ||||
| 
 | ||||
| # Docker | ||||
| .docker/config/* | ||||
| !.docker/config/.keep | ||||
| @ -1,8 +1,8 @@ | ||||
| FROM node:lts-alpine | ||||
| RUN mkdir -p /usr/src/fosscord-api | ||||
| WORKDIR /usr/src/fosscord-api | ||||
| COPY package.json /usr/src/fosscord-api | ||||
| COPY package.json .  | ||||
| RUN npm install | ||||
| COPY . /usr/src/fosscord-api | ||||
| RUN npx patch-package | ||||
| COPY . . | ||||
| EXPOSE 3001 | ||||
| CMD ["npm", "start"] | ||||
| @ -18,6 +18,7 @@ | ||||
| 				MEDIA_PROXY_ENDPOINT: "https://media.discordapp.net", | ||||
| 				WIDGET_ENDPOINT: "//discord.com/widget", | ||||
| 				INVITE_HOST: "discord.gg", | ||||
| 
 | ||||
| 				GUILD_TEMPLATE_HOST: "discord.new", | ||||
| 				GIFT_CODE_HOST: "discord.gift", | ||||
| 				RELEASE_CHANNEL: "stable", | ||||
| @ -32,10 +33,9 @@ | ||||
| 				MIGRATION_SOURCE_ORIGIN: "https://discordapp.com", | ||||
| 				MIGRATION_DESTINATION_ORIGIN: "https://discord.com", | ||||
| 				HTML_TIMESTAMP: Date.now(), | ||||
| 				ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0", | ||||
| 				ALGOLIA_KEY: "aca0d7082e4e63af5ba5917d5e96bed0" | ||||
| 			}; | ||||
| 		</script> | ||||
| 		<script> | ||||
| 			localStorage.removeItem("gatewayURL"); | ||||
| 			localStorage.setItem( | ||||
| 				"DeveloperOptionsStore", | ||||
| 				`{"trace":false,"canary":false,"logGatewayEvents":true,"logOverlayEvents":false,"logAnalyticsEvents":false,"sourceMapsEnabled":false,"axeEnabled":false}` | ||||
|  | ||||
| @ -1,15 +1,15 @@ | ||||
| { | ||||
| 	"login": { | ||||
| 		"INVALID_LOGIN": "E-Mail or Phone not found", | ||||
| 		"INVALID_PASSWORD": "Invalid Password" | ||||
| 		"INVALID_LOGIN": "找不到电子邮件或电话", | ||||
| 		"INVALID_PASSWORD": "无效密码" | ||||
| 	}, | ||||
| 	"register": { | ||||
| 		"REGISTRATION_DISABLED": "New user registration is disabled", | ||||
| 		"INVITE_ONLY": "You must be invited to register", | ||||
| 		"REGISTRATION_DISABLED": "新用户注册已禁用", | ||||
| 		"INVITE_ONLY": "您必须被邀请注册", | ||||
| 		"EMAIL_INVALID": "Invalid Email", | ||||
| 		"EMAIL_ALREADY_REGISTERED": "Email is already registered", | ||||
| 		"DATE_OF_BIRTH_UNDERAGE": "You need to be {{years}} years or older", | ||||
| 		"CONSENT_REQUIRED": "You must agree to Terms of Service and Privacy Policy.", | ||||
| 		"USERNAME_TOO_MANY_USERS": "Too many users have this username, please try another" | ||||
| 		"EMAIL_ALREADY_REGISTERED": "电子邮件已注册", | ||||
| 		"DATE_OF_BIRTH_UNDERAGE": "您需要有 {{years}} 岁以上", | ||||
| 		"CONSENT_REQUIRED": "您必须同意服务条款和隐私政策。", | ||||
| 		"USERNAME_TOO_MANY_USERS": "用户名太多,请尝试另一个" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1,18 +1,18 @@ | ||||
| { | ||||
|   "field": { | ||||
|     "BASE_TYPE_REQUIRED": "This field is required", | ||||
|     "BASE_TYPE_STRING": "This field must be a string", | ||||
|     "BASE_TYPE_NUMBER": "This field must be a number", | ||||
|     "BASE_TYPE_BIGINT": "This field must be a bigint", | ||||
|     "BASE_TYPE_BOOLEAN": "This field must be a boolean", | ||||
|     "BASE_TYPE_CHOICES": "This field must be one of ({{types}})", | ||||
|     "BASE_TYPE_CLASS": "This field must be an instance of {{type}}", | ||||
|     "BASE_TYPE_OBJECT": "This field must be a object", | ||||
|     "BASE_TYPE_ARRAY": "This field must be an array", | ||||
|     "UNKOWN_FIELD": "Unkown key: {{key}}", | ||||
|     "BASE_TYPE_CONSTANT": "This field must be {{value}}", | ||||
|     "EMAIL_TYPE_INVALID_EMAIL": "Not a well formed email address", | ||||
|     "DATE_TYPE_PARSE": "Could not parse {{date}}. Should be ISO8601", | ||||
|     "BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length" | ||||
|     "BASE_TYPE_REQUIRED": "此字段是必填项", | ||||
|     "BASE_TYPE_STRING": "此字段必须是字符串", | ||||
|     "BASE_TYPE_NUMBER": "此字段必须是一个数字", | ||||
|     "BASE_TYPE_BIGINT": "此字段必须是很大的", | ||||
|     "BASE_TYPE_BOOLEAN": "此字段必须是布尔值", | ||||
|     "BASE_TYPE_CHOICES": "此字段必须是 ({{types}})", | ||||
|     "BASE_TYPE_CLASS": "此字段必须是 {{type}} 的实例", | ||||
|     "BASE_TYPE_OBJECT": "此字段必须是对象", | ||||
|     "BASE_TYPE_ARRAY": "此字段必须是一个数组", | ||||
|     "UNKOWN_FIELD": "未知密钥: {{key}}", | ||||
|     "BASE_TYPE_CONSTANT": "此字段必须是 {{value}}", | ||||
|     "EMAIL_TYPE_INVALID_EMAIL": "格式不正确的电子邮件地址", | ||||
|     "DATE_TYPE_PARSE": "无法解析 {{date}}。应该为 ISO8601", | ||||
|     "BASE_TYPE_BAD_LENGTH": "长度必须介于 {{length}} 之间" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										358
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										358
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -7,14 +7,20 @@ | ||||
| 		"": { | ||||
| 			"name": "@fosscord/api", | ||||
| 			"version": "1.0.0", | ||||
| 			"hasInstallScript": true, | ||||
| 			"license": "ISC", | ||||
| 			"dependencies": { | ||||
| 				"@fosscord/server-util": "^1.2.6", | ||||
| 				"@fosscord/server-util": "^1.3.5", | ||||
| 				"@types/jest": "^26.0.22", | ||||
| 				"@types/json-schema": "^7.0.7", | ||||
| 				"ajv": "^8.4.0", | ||||
| 				"ajv-formats": "^2.1.0", | ||||
| 				"assert": "^1.5.0", | ||||
| 				"atomically": "^1.7.0", | ||||
| 				"bcrypt": "^5.0.1", | ||||
| 				"body-parser": "^1.19.0", | ||||
| 				"dot-prop": "^6.0.1", | ||||
| 				"dotenv": "^8.2.0", | ||||
| 				"env-paths": "^2.2.1", | ||||
| 				"express": "^4.17.1", | ||||
| 				"express-validator": "^6.9.2", | ||||
| 				"i18next": "^19.8.5", | ||||
| @ -46,6 +52,27 @@ | ||||
| 				"typescript": "^4.1.2" | ||||
| 			} | ||||
| 		}, | ||||
| 		"../server-util": { | ||||
| 			"name": "@fosscord/server-util", | ||||
| 			"version": "1.3.4", | ||||
| 			"extraneous": true, | ||||
| 			"license": "ISC", | ||||
| 			"dependencies": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| 				"@types/mongoose-lean-virtuals": "^0.5.1", | ||||
| 				"@types/node": "^14.14.25", | ||||
| 				"ajv": "^8.5.0", | ||||
| 				"dot-prop": "^6.0.1", | ||||
| 				"env-paths": "^2.2.1", | ||||
| 				"jsonwebtoken": "^8.5.1", | ||||
| 				"missing-native-js-functions": "^1.2.2", | ||||
| 				"mongodb": "^3.6.8", | ||||
| 				"mongoose": "^5.12.3", | ||||
| 				"mongoose-autopopulate": "^0.12.3", | ||||
| 				"typescript": "^4.1.3" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@babel/code-frame": { | ||||
| 			"version": "7.12.13", | ||||
| 			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", | ||||
| @ -492,31 +519,34 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@fosscord/server-util": { | ||||
| 			"version": "1.2.6", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.2.6.tgz", | ||||
| 			"integrity": "sha512-HFa/DX+4Ze9e8j/tT/Je6at2UEygAH4xsHYay/SObFQKC1Oo+G5aIYvak0kwyzO12lg91i0FBRUEHuMviwNe8A==", | ||||
| 			"version": "1.3.5", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.5.tgz", | ||||
| 			"integrity": "sha512-gXtpiw1LoGeYxmIOKHVv6iAShye6SVYKuwjvLrnsrAXPeyE3h5/YwYAEnjycuKIVjafF9RVBWluWzWSj/TOPbA==", | ||||
| 			"dependencies": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| 				"@types/mongoose-lean-virtuals": "^0.5.1", | ||||
| 				"@types/node": "^14.14.25", | ||||
| 				"ajv": "^8.5.0", | ||||
| 				"dot-prop": "^6.0.1", | ||||
| 				"env-paths": "^2.2.1", | ||||
| 				"jsonwebtoken": "^8.5.1", | ||||
| 				"missing-native-js-functions": "^1.2.2", | ||||
| 				"mongodb": "^3.6.6", | ||||
| 				"mongodb": "^3.6.8", | ||||
| 				"mongoose": "^5.12.3", | ||||
| 				"mongoose-autopopulate": "^0.12.3", | ||||
| 				"typescript": "^4.1.3" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@fosscord/server-util/node_modules/mongodb": { | ||||
| 			"version": "3.6.6", | ||||
| 			"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz", | ||||
| 			"integrity": "sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w==", | ||||
| 			"version": "3.6.8", | ||||
| 			"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz", | ||||
| 			"integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==", | ||||
| 			"dependencies": { | ||||
| 				"bl": "^2.2.1", | ||||
| 				"bson": "^1.1.4", | ||||
| 				"denque": "^1.4.1", | ||||
| 				"optional-require": "^1.0.2", | ||||
| 				"optional-require": "^1.0.3", | ||||
| 				"safe-buffer": "^5.1.2" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| @ -524,6 +554,26 @@ | ||||
| 			}, | ||||
| 			"optionalDependencies": { | ||||
| 				"saslprep": "^1.0.0" | ||||
| 			}, | ||||
| 			"peerDependenciesMeta": { | ||||
| 				"aws4": { | ||||
| 					"optional": true | ||||
| 				}, | ||||
| 				"bson-ext": { | ||||
| 					"optional": true | ||||
| 				}, | ||||
| 				"kerberos": { | ||||
| 					"optional": true | ||||
| 				}, | ||||
| 				"mongodb-client-encryption": { | ||||
| 					"optional": true | ||||
| 				}, | ||||
| 				"mongodb-extjson": { | ||||
| 					"optional": true | ||||
| 				}, | ||||
| 				"snappy": { | ||||
| 					"optional": true | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@istanbuljs/load-nyc-config": { | ||||
| @ -1513,6 +1563,11 @@ | ||||
| 				"pretty-format": "^26.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@types/json-schema": { | ||||
| 			"version": "7.0.7", | ||||
| 			"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", | ||||
| 			"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" | ||||
| 		}, | ||||
| 		"node_modules/@types/jsonwebtoken": { | ||||
| 			"version": "8.5.0", | ||||
| 			"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz", | ||||
| @ -1710,6 +1765,28 @@ | ||||
| 				"node": ">=8.5.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/0x/node_modules/ajv": { | ||||
| 			"version": "6.12.6", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", | ||||
| 			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"fast-deep-equal": "^3.1.1", | ||||
| 				"fast-json-stable-stringify": "^2.0.0", | ||||
| 				"json-schema-traverse": "^0.4.1", | ||||
| 				"uri-js": "^4.2.2" | ||||
| 			}, | ||||
| 			"funding": { | ||||
| 				"type": "github", | ||||
| 				"url": "https://github.com/sponsors/epoberezkin" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/0x/node_modules/json-schema-traverse": { | ||||
| 			"version": "0.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
| 			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/0x/node_modules/make-dir": { | ||||
| 			"version": "1.3.0", | ||||
| 			"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", | ||||
| @ -1811,15 +1888,34 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ajv": { | ||||
| 			"version": "6.12.6", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", | ||||
| 			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", | ||||
| 			"dev": true, | ||||
| 			"version": "8.5.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", | ||||
| 			"integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", | ||||
| 			"dependencies": { | ||||
| 				"fast-deep-equal": "^3.1.1", | ||||
| 				"fast-json-stable-stringify": "^2.0.0", | ||||
| 				"json-schema-traverse": "^0.4.1", | ||||
| 				"json-schema-traverse": "^1.0.0", | ||||
| 				"require-from-string": "^2.0.2", | ||||
| 				"uri-js": "^4.2.2" | ||||
| 			}, | ||||
| 			"funding": { | ||||
| 				"type": "github", | ||||
| 				"url": "https://github.com/sponsors/epoberezkin" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ajv-formats": { | ||||
| 			"version": "2.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", | ||||
| 			"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", | ||||
| 			"dependencies": { | ||||
| 				"ajv": "^8.0.0" | ||||
| 			}, | ||||
| 			"peerDependencies": { | ||||
| 				"ajv": "^8.0.0" | ||||
| 			}, | ||||
| 			"peerDependenciesMeta": { | ||||
| 				"ajv": { | ||||
| 					"optional": true | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ansi-escapes": { | ||||
| @ -1987,7 +2083,6 @@ | ||||
| 			"version": "1.5.0", | ||||
| 			"resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", | ||||
| 			"integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"object-assign": "^4.1.1", | ||||
| 				"util": "0.10.3" | ||||
| @ -2005,14 +2100,12 @@ | ||||
| 		"node_modules/assert/node_modules/inherits": { | ||||
| 			"version": "2.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", | ||||
| 			"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", | ||||
| 			"dev": true | ||||
| 			"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" | ||||
| 		}, | ||||
| 		"node_modules/assert/node_modules/util": { | ||||
| 			"version": "0.10.3", | ||||
| 			"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", | ||||
| 			"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"inherits": "2.0.1" | ||||
| 			} | ||||
| @ -2044,6 +2137,14 @@ | ||||
| 				"node": ">= 4.5.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/atomically": { | ||||
| 			"version": "1.7.0", | ||||
| 			"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", | ||||
| 			"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", | ||||
| 			"engines": { | ||||
| 				"node": ">=10.12.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/aws-sign2": { | ||||
| 			"version": "0.7.0", | ||||
| 			"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", | ||||
| @ -3871,6 +3972,20 @@ | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/dot-prop": { | ||||
| 			"version": "6.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", | ||||
| 			"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", | ||||
| 			"dependencies": { | ||||
| 				"is-obj": "^2.0.0" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=10" | ||||
| 			}, | ||||
| 			"funding": { | ||||
| 				"url": "https://github.com/sponsors/sindresorhus" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/dotenv": { | ||||
| 			"version": "8.2.0", | ||||
| 			"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", | ||||
| @ -3991,6 +4106,14 @@ | ||||
| 				"once": "^1.4.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/env-paths": { | ||||
| 			"version": "2.2.1", | ||||
| 			"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", | ||||
| 			"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", | ||||
| 			"engines": { | ||||
| 				"node": ">=6" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/env-string": { | ||||
| 			"version": "1.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/env-string/-/env-string-1.0.1.tgz", | ||||
| @ -4493,8 +4616,7 @@ | ||||
| 		"node_modules/fast-deep-equal": { | ||||
| 			"version": "3.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", | ||||
| 			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", | ||||
| 			"dev": true | ||||
| 			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" | ||||
| 		}, | ||||
| 		"node_modules/fast-json-stable-stringify": { | ||||
| 			"version": "2.1.0", | ||||
| @ -4856,6 +4978,28 @@ | ||||
| 				"node": ">=6" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/har-validator/node_modules/ajv": { | ||||
| 			"version": "6.12.6", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", | ||||
| 			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"fast-deep-equal": "^3.1.1", | ||||
| 				"fast-json-stable-stringify": "^2.0.0", | ||||
| 				"json-schema-traverse": "^0.4.1", | ||||
| 				"uri-js": "^4.2.2" | ||||
| 			}, | ||||
| 			"funding": { | ||||
| 				"type": "github", | ||||
| 				"url": "https://github.com/sponsors/epoberezkin" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/har-validator/node_modules/json-schema-traverse": { | ||||
| 			"version": "0.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
| 			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/has": { | ||||
| 			"version": "1.0.3", | ||||
| 			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", | ||||
| @ -5443,6 +5587,14 @@ | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/is-obj": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", | ||||
| 			"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", | ||||
| 			"engines": { | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/is-plain-object": { | ||||
| 			"version": "2.0.4", | ||||
| 			"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", | ||||
| @ -7422,10 +7574,9 @@ | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/json-schema-traverse": { | ||||
| 			"version": "0.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
| 			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", | ||||
| 			"dev": true | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", | ||||
| 			"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" | ||||
| 		}, | ||||
| 		"node_modules/json-stable-stringify": { | ||||
| 			"version": "0.0.1", | ||||
| @ -9777,6 +9928,14 @@ | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/require-from-string": { | ||||
| 			"version": "2.0.2", | ||||
| 			"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", | ||||
| 			"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", | ||||
| 			"engines": { | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/require-main-filename": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", | ||||
| @ -10626,6 +10785,11 @@ | ||||
| 				"safer-buffer": "^2.0.2", | ||||
| 				"tweetnacl": "~0.14.0" | ||||
| 			}, | ||||
| 			"bin": { | ||||
| 				"sshpk-conv": "bin/sshpk-conv", | ||||
| 				"sshpk-sign": "bin/sshpk-sign", | ||||
| 				"sshpk-verify": "bin/sshpk-verify" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| @ -11454,9 +11618,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/typescript": { | ||||
| 			"version": "4.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", | ||||
| 			"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", | ||||
| 			"version": "4.2.4", | ||||
| 			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", | ||||
| 			"integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", | ||||
| 			"bin": { | ||||
| 				"tsc": "bin/tsc", | ||||
| 				"tsserver": "bin/tsserver" | ||||
| @ -11589,7 +11753,6 @@ | ||||
| 			"version": "4.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", | ||||
| 			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"punycode": "^2.1.0" | ||||
| 			} | ||||
| @ -11598,7 +11761,6 @@ | ||||
| 			"version": "2.1.1", | ||||
| 			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", | ||||
| 			"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", | ||||
| 			"dev": true, | ||||
| 			"engines": { | ||||
| 				"node": ">=6" | ||||
| 			} | ||||
| @ -12531,31 +12693,34 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"@fosscord/server-util": { | ||||
| 			"version": "1.2.6", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.2.6.tgz", | ||||
| 			"integrity": "sha512-HFa/DX+4Ze9e8j/tT/Je6at2UEygAH4xsHYay/SObFQKC1Oo+G5aIYvak0kwyzO12lg91i0FBRUEHuMviwNe8A==", | ||||
| 			"version": "1.3.5", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.5.tgz", | ||||
| 			"integrity": "sha512-gXtpiw1LoGeYxmIOKHVv6iAShye6SVYKuwjvLrnsrAXPeyE3h5/YwYAEnjycuKIVjafF9RVBWluWzWSj/TOPbA==", | ||||
| 			"requires": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| 				"@types/mongoose-lean-virtuals": "^0.5.1", | ||||
| 				"@types/node": "^14.14.25", | ||||
| 				"ajv": "^8.5.0", | ||||
| 				"dot-prop": "^6.0.1", | ||||
| 				"env-paths": "^2.2.1", | ||||
| 				"jsonwebtoken": "^8.5.1", | ||||
| 				"missing-native-js-functions": "^1.2.2", | ||||
| 				"mongodb": "^3.6.6", | ||||
| 				"mongodb": "^3.6.8", | ||||
| 				"mongoose": "^5.12.3", | ||||
| 				"mongoose-autopopulate": "^0.12.3", | ||||
| 				"typescript": "^4.1.3" | ||||
| 			}, | ||||
| 			"dependencies": { | ||||
| 				"mongodb": { | ||||
| 					"version": "3.6.6", | ||||
| 					"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz", | ||||
| 					"integrity": "sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w==", | ||||
| 					"version": "3.6.8", | ||||
| 					"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz", | ||||
| 					"integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==", | ||||
| 					"requires": { | ||||
| 						"bl": "^2.2.1", | ||||
| 						"bson": "^1.1.4", | ||||
| 						"denque": "^1.4.1", | ||||
| 						"optional-require": "^1.0.2", | ||||
| 						"optional-require": "^1.0.3", | ||||
| 						"safe-buffer": "^5.1.2", | ||||
| 						"saslprep": "^1.0.0" | ||||
| 					} | ||||
| @ -13375,6 +13540,11 @@ | ||||
| 				"pretty-format": "^26.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"@types/json-schema": { | ||||
| 			"version": "7.0.7", | ||||
| 			"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", | ||||
| 			"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" | ||||
| 		}, | ||||
| 		"@types/jsonwebtoken": { | ||||
| 			"version": "8.5.0", | ||||
| 			"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz", | ||||
| @ -13566,6 +13736,24 @@ | ||||
| 				"which": "^1.2.4" | ||||
| 			}, | ||||
| 			"dependencies": { | ||||
| 				"ajv": { | ||||
| 					"version": "6.12.6", | ||||
| 					"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", | ||||
| 					"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", | ||||
| 					"dev": true, | ||||
| 					"requires": { | ||||
| 						"fast-deep-equal": "^3.1.1", | ||||
| 						"fast-json-stable-stringify": "^2.0.0", | ||||
| 						"json-schema-traverse": "^0.4.1", | ||||
| 						"uri-js": "^4.2.2" | ||||
| 					} | ||||
| 				}, | ||||
| 				"json-schema-traverse": { | ||||
| 					"version": "0.4.1", | ||||
| 					"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
| 					"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", | ||||
| 					"dev": true | ||||
| 				}, | ||||
| 				"make-dir": { | ||||
| 					"version": "1.3.0", | ||||
| 					"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", | ||||
| @ -13648,17 +13836,24 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"ajv": { | ||||
| 			"version": "6.12.6", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", | ||||
| 			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", | ||||
| 			"dev": true, | ||||
| 			"version": "8.5.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", | ||||
| 			"integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", | ||||
| 			"requires": { | ||||
| 				"fast-deep-equal": "^3.1.1", | ||||
| 				"fast-json-stable-stringify": "^2.0.0", | ||||
| 				"json-schema-traverse": "^0.4.1", | ||||
| 				"json-schema-traverse": "^1.0.0", | ||||
| 				"require-from-string": "^2.0.2", | ||||
| 				"uri-js": "^4.2.2" | ||||
| 			} | ||||
| 		}, | ||||
| 		"ajv-formats": { | ||||
| 			"version": "2.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", | ||||
| 			"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", | ||||
| 			"requires": { | ||||
| 				"ajv": "^8.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"ansi-escapes": { | ||||
| 			"version": "4.3.2", | ||||
| 			"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", | ||||
| @ -13799,7 +13994,6 @@ | ||||
| 			"version": "1.5.0", | ||||
| 			"resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", | ||||
| 			"integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"object-assign": "^4.1.1", | ||||
| 				"util": "0.10.3" | ||||
| @ -13808,14 +14002,12 @@ | ||||
| 				"inherits": { | ||||
| 					"version": "2.0.1", | ||||
| 					"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", | ||||
| 					"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", | ||||
| 					"dev": true | ||||
| 					"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" | ||||
| 				}, | ||||
| 				"util": { | ||||
| 					"version": "0.10.3", | ||||
| 					"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", | ||||
| 					"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", | ||||
| 					"dev": true, | ||||
| 					"requires": { | ||||
| 						"inherits": "2.0.1" | ||||
| 					} | ||||
| @ -13846,6 +14038,11 @@ | ||||
| 			"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"atomically": { | ||||
| 			"version": "1.7.0", | ||||
| 			"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", | ||||
| 			"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==" | ||||
| 		}, | ||||
| 		"aws-sign2": { | ||||
| 			"version": "0.7.0", | ||||
| 			"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", | ||||
| @ -15431,6 +15628,14 @@ | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"dot-prop": { | ||||
| 			"version": "6.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", | ||||
| 			"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", | ||||
| 			"requires": { | ||||
| 				"is-obj": "^2.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"dotenv": { | ||||
| 			"version": "8.2.0", | ||||
| 			"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", | ||||
| @ -15544,6 +15749,11 @@ | ||||
| 				"once": "^1.4.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"env-paths": { | ||||
| 			"version": "2.2.1", | ||||
| 			"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", | ||||
| 			"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" | ||||
| 		}, | ||||
| 		"env-string": { | ||||
| 			"version": "1.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/env-string/-/env-string-1.0.1.tgz", | ||||
| @ -15957,8 +16167,7 @@ | ||||
| 		"fast-deep-equal": { | ||||
| 			"version": "3.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", | ||||
| 			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", | ||||
| 			"dev": true | ||||
| 			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" | ||||
| 		}, | ||||
| 		"fast-json-stable-stringify": { | ||||
| 			"version": "2.1.0", | ||||
| @ -16247,6 +16456,26 @@ | ||||
| 			"requires": { | ||||
| 				"ajv": "^6.12.3", | ||||
| 				"har-schema": "^2.0.0" | ||||
| 			}, | ||||
| 			"dependencies": { | ||||
| 				"ajv": { | ||||
| 					"version": "6.12.6", | ||||
| 					"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", | ||||
| 					"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", | ||||
| 					"dev": true, | ||||
| 					"requires": { | ||||
| 						"fast-deep-equal": "^3.1.1", | ||||
| 						"fast-json-stable-stringify": "^2.0.0", | ||||
| 						"json-schema-traverse": "^0.4.1", | ||||
| 						"uri-js": "^4.2.2" | ||||
| 					} | ||||
| 				}, | ||||
| 				"json-schema-traverse": { | ||||
| 					"version": "0.4.1", | ||||
| 					"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
| 					"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", | ||||
| 					"dev": true | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"has": { | ||||
| @ -16731,6 +16960,11 @@ | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"is-obj": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", | ||||
| 			"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" | ||||
| 		}, | ||||
| 		"is-plain-object": { | ||||
| 			"version": "2.0.4", | ||||
| 			"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", | ||||
| @ -18305,10 +18539,9 @@ | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"json-schema-traverse": { | ||||
| 			"version": "0.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||||
| 			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", | ||||
| 			"dev": true | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", | ||||
| 			"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" | ||||
| 		}, | ||||
| 		"json-stable-stringify": { | ||||
| 			"version": "0.0.1", | ||||
| @ -20266,6 +20499,11 @@ | ||||
| 			"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"require-from-string": { | ||||
| 			"version": "2.0.2", | ||||
| 			"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", | ||||
| 			"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" | ||||
| 		}, | ||||
| 		"require-main-filename": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", | ||||
| @ -21662,9 +21900,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"typescript": { | ||||
| 			"version": "4.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", | ||||
| 			"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==" | ||||
| 			"version": "4.2.4", | ||||
| 			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", | ||||
| 			"integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==" | ||||
| 		}, | ||||
| 		"umd": { | ||||
| 			"version": "3.0.3", | ||||
| @ -21766,7 +22004,6 @@ | ||||
| 			"version": "4.4.1", | ||||
| 			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", | ||||
| 			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"punycode": "^2.1.0" | ||||
| 			}, | ||||
| @ -21774,8 +22011,7 @@ | ||||
| 				"punycode": { | ||||
| 					"version": "2.1.1", | ||||
| 					"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", | ||||
| 					"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", | ||||
| 					"dev": true | ||||
| 					"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| @ -29,11 +29,18 @@ | ||||
| 	}, | ||||
| 	"homepage": "https://github.com/fosscord/fosscord-api#readme", | ||||
| 	"dependencies": { | ||||
| 		"@fosscord/server-util": "^1.2.6", | ||||
| 		"@fosscord/server-util": "^1.3.5", | ||||
| 		"@types/jest": "^26.0.22", | ||||
| 		"@types/json-schema": "^7.0.7", | ||||
| 		"ajv": "^8.4.0", | ||||
| 		"ajv-formats": "^2.1.0", | ||||
| 		"assert": "^1.5.0", | ||||
| 		"atomically": "^1.7.0", | ||||
| 		"bcrypt": "^5.0.1", | ||||
| 		"body-parser": "^1.19.0", | ||||
| 		"dot-prop": "^6.0.1", | ||||
| 		"dotenv": "^8.2.0", | ||||
| 		"env-paths": "^2.2.1", | ||||
| 		"express": "^4.17.1", | ||||
| 		"express-validator": "^6.9.2", | ||||
| 		"i18next": "^19.8.5", | ||||
|  | ||||
							
								
								
									
										93
									
								
								scripts/config_generator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								scripts/config_generator.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| const { Snowflake } = require("@fosscord/server-util"); | ||||
| const crypto = require('crypto'); | ||||
| const fs = require('fs'); | ||||
| 
 | ||||
| 
 | ||||
| const defaultConfig = { | ||||
|     // TODO: Get the network interfaces dinamically
 | ||||
|     gateway: "ws://localhost", | ||||
|     general: { | ||||
|         instance_id: Snowflake.generate(), | ||||
|     }, | ||||
|     permissions: { | ||||
|         user: { | ||||
|             createGuilds: true, | ||||
|         } | ||||
|     }, | ||||
|     limits: { | ||||
|         user: { | ||||
|             maxGuilds: 100, | ||||
|             maxUsername: 32, | ||||
|             maxFriends: 1000, | ||||
|         }, | ||||
|         guild: { | ||||
|             maxRoles: 250, | ||||
|             maxMembers: 250000, | ||||
|             maxChannels: 500, | ||||
|             maxChannelsInCategory: 50, | ||||
|             hideOfflineMember: 1000, | ||||
|         }, | ||||
|         message: { | ||||
| 			characters: 2000, | ||||
| 			ttsCharacters: 200, | ||||
| 			maxReactions: 20, | ||||
| 			maxAttachmentSize: 8388608, | ||||
| 			maxBulkDelete: 100, | ||||
| 		}, | ||||
| 		channel: { | ||||
| 			maxPins: 50, | ||||
| 			maxTopic: 1024, | ||||
| 		}, | ||||
| 		rate: { | ||||
| 			ip: { | ||||
| 				enabled: true, | ||||
| 				count: 1000, | ||||
| 				timespan: 1000 * 60 * 10, | ||||
| 			}, | ||||
| 			routes: {}, | ||||
| 		}, | ||||
| 	}, | ||||
| 	security: { | ||||
| 		jwtSecret: crypto.randomBytes(256).toString("base64"), | ||||
| 		forwadedFor: null, | ||||
| 		// forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
 | ||||
| 		// forwadedFor: "CF-Connecting-IP" // cloudflare:
 | ||||
| 		captcha: { | ||||
| 			enabled: false, | ||||
| 			service: null, | ||||
| 			sitekey: null, | ||||
| 			secret: null, | ||||
| 		}, | ||||
| 	}, | ||||
| 	login: { | ||||
| 		requireCaptcha: false, | ||||
| 	}, | ||||
| 	register: { | ||||
| 		email: { | ||||
| 			necessary: true, | ||||
| 			allowlist: false, | ||||
| 			blocklist: true, | ||||
| 			domains: [], // TODO: efficiently save domain blocklist in database
 | ||||
| 			// domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
 | ||||
| 		}, | ||||
| 		dateOfBirth: { | ||||
| 			necessary: true, | ||||
| 			minimum: 13, | ||||
| 		}, | ||||
| 		requireInvite: false, | ||||
| 		requireCaptcha: true, | ||||
| 		allowNewRegistration: true, | ||||
| 		allowMultipleAccounts: true, | ||||
| 		password: { | ||||
| 			minLength: 8, | ||||
| 			minNumbers: 2, | ||||
| 			minUpperCase: 2, | ||||
| 			minSymbols: 0, | ||||
| 			blockInsecureCommonPasswords: false, | ||||
| 		}, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| let data = JSON.stringify(defaultConfig); | ||||
| fs.writeFileSync('./.docker/config/api.json', data); | ||||
| 
 | ||||
| @ -3,16 +3,16 @@ import fs from "fs/promises"; | ||||
| import { Connection } from "mongoose"; | ||||
| import { Server, ServerOptions } from "lambert-server"; | ||||
| import { Authentication, CORS, GlobalRateLimit } from "./middlewares/"; | ||||
| import Config from "./util/Config"; | ||||
| import { db } from "@fosscord/server-util"; | ||||
| import { Config, db } from "@fosscord/server-util"; | ||||
| import i18next from "i18next"; | ||||
| import i18nextMiddleware, { I18next } from "i18next-http-middleware"; | ||||
| import i18nextBackend from "i18next-node-fs-backend"; | ||||
| import { ErrorHandler } from "./middlewares/ErrorHandler"; | ||||
| import { BodyParser } from "./middlewares/BodyParser"; | ||||
| import { Router } from "express"; | ||||
| import express, { Router } from "express"; | ||||
| import fetch from "node-fetch"; | ||||
| import mongoose from "mongoose"; | ||||
| import path from "path"; | ||||
| 
 | ||||
| // this will return the new updated document for findOneAndUpdate
 | ||||
| mongoose.set("returnOriginal", false); // https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndUpdate
 | ||||
| @ -55,14 +55,14 @@ export class FosscordServer extends Server { | ||||
| 		await (db as Promise<Connection>); | ||||
| 		await this.setupSchema(); | ||||
| 		console.log("[DB] connected"); | ||||
| 		await Promise.all([Config.init()]); | ||||
| 		await Config.init(); | ||||
| 
 | ||||
| 		this.app.use(GlobalRateLimit); | ||||
| 		this.app.use(Authentication); | ||||
| 		this.app.use(CORS); | ||||
| 		this.app.use(BodyParser({ inflate: true })); | ||||
| 		const languages = await fs.readdir(__dirname + "/../locales/"); | ||||
| 		const namespaces = await fs.readdir(__dirname + "/../locales/en/"); | ||||
| 		const languages = await fs.readdir(path.join(__dirname, "..", "locales")); | ||||
| 		const namespaces = await fs.readdir(path.join(__dirname, "..", "locales", "en")); | ||||
| 		const ns = namespaces.filter((x) => x.endsWith(".json")).map((x) => x.slice(0, x.length - 5)); | ||||
| 
 | ||||
| 		await i18next | ||||
| @ -85,11 +85,13 @@ export class FosscordServer extends Server { | ||||
| 		// @ts-ignore
 | ||||
| 		this.app = prefix; | ||||
| 
 | ||||
| 		this.routes = await this.registerRoutes(__dirname + "/routes/"); | ||||
| 		this.routes = await this.registerRoutes(path.join(__dirname, "routes", "/")); | ||||
| 		app.use("/api/v8", prefix); | ||||
| 		this.app = app; | ||||
| 		this.app.use(ErrorHandler); | ||||
| 		const indexHTML = await fs.readFile(__dirname + "/../client_test/index.html"); | ||||
| 		const indexHTML = await fs.readFile(path.join(__dirname, "..", "client_test", "index.html")); | ||||
| 
 | ||||
| 		this.app.use("/assets", express.static(path.join(__dirname, "..", "assets"))); | ||||
| 
 | ||||
| 		this.app.get("/assets/:file", async (req, res) => { | ||||
| 			delete req.headers.host; | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| import { NextFunction, Request, Response } from "express"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import { checkToken } from "@fosscord/server-util"; | ||||
| import { checkToken, Config } from "@fosscord/server-util"; | ||||
| 
 | ||||
| export const NO_AUTHORIZATION_ROUTES = [ | ||||
| 	"/api/v8/auth/login", | ||||
| 	"/api/v8/auth/register", | ||||
| 	"/api/v8/webhooks/", | ||||
| 	"/api/v8/gateway", | ||||
| 	"/api/v8/experiments", | ||||
| 	"/api/v8/experiments" | ||||
| ]; | ||||
| 
 | ||||
| declare global { | ||||
| @ -24,10 +24,11 @@ export async function Authentication(req: Request, res: Response, next: NextFunc | ||||
| 	if (req.url.startsWith("/api/v8/invites") && req.method === "GET") return next(); | ||||
| 	if (NO_AUTHORIZATION_ROUTES.some((x) => req.url.startsWith(x))) return next(); | ||||
| 	if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401)); | ||||
| 	// TODO: check if user is banned/token expired
 | ||||
| 
 | ||||
| 	try { | ||||
| 		const decoded: any = await checkToken(req.headers.authorization); | ||||
| 		const { jwtSecret } = Config.get().security; | ||||
| 
 | ||||
| 		const decoded: any = await checkToken(req.headers.authorization, jwtSecret); | ||||
| 
 | ||||
| 		req.token = decoded; | ||||
| 		req.user_id = decoded.id; | ||||
|  | ||||
| @ -9,7 +9,7 @@ export function CORS(req: Request, res: Response, next: NextFunction) { | ||||
| 		"Content-security-policy", | ||||
| 		"default-src *  data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval'; script-src * data: blob: 'unsafe-inline' 'unsafe-eval'; connect-src * data: blob: 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src * data: blob: ; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';" | ||||
| 	); | ||||
| 	res.set("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers")); | ||||
| 	res.set("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers") || "*"); | ||||
| 
 | ||||
| 	next(); | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { NextFunction, Request, Response } from "express"; | ||||
| import Config from "../util/Config"; | ||||
| import { Config } from "@fosscord/server-util"; | ||||
| 
 | ||||
| // TODO: use mongodb ttl index
 | ||||
| // TODO: increment count on serverside
 | ||||
|  | ||||
| @ -2,8 +2,7 @@ import { Request, Response, Router } from "express"; | ||||
| import { check, FieldErrors, Length } from "../../util/instanceOf"; | ||||
| import bcrypt from "bcrypt"; | ||||
| import jwt from "jsonwebtoken"; | ||||
| import { UserModel } from "@fosscord/server-util"; | ||||
| import Config from "../../util/Config"; | ||||
| import { Config, UserModel } from "@fosscord/server-util"; | ||||
| import { adjustEmail } from "./register"; | ||||
| 
 | ||||
| const router: Router = Router(); | ||||
| @ -17,7 +16,7 @@ router.post( | ||||
| 		$undelete: Boolean, | ||||
| 		$captcha_key: String, | ||||
| 		$login_source: String, | ||||
| 		$gift_code_sku_id: String, | ||||
| 		$gift_code_sku_id: String | ||||
| 	}), | ||||
| 	async (req: Request, res: Response) => { | ||||
| 		const { login, password, captcha_key } = req.body; | ||||
| @ -25,6 +24,8 @@ router.post( | ||||
| 		const query: any[] = [{ phone: login }]; | ||||
| 		if (email) query.push({ email }); | ||||
| 
 | ||||
| 		// TODO: Rewrite this to have the proper config syntax on the new method
 | ||||
| 
 | ||||
| 		const config = Config.get(); | ||||
| 
 | ||||
| 		if (config.login.requireCaptcha && config.security.captcha.enabled) { | ||||
| @ -33,7 +34,7 @@ router.post( | ||||
| 				return res.status(400).json({ | ||||
| 					captcha_key: ["captcha-required"], | ||||
| 					captcha_sitekey: sitekey, | ||||
| 					captcha_service: service, | ||||
| 					captcha_service: service | ||||
| 				}); | ||||
| 			} | ||||
| 
 | ||||
| @ -71,7 +72,7 @@ export async function generateToken(id: string) { | ||||
| 			{ id: id, iat }, | ||||
| 			Config.get().security.jwtSecret, | ||||
| 			{ | ||||
| 				algorithm, | ||||
| 				algorithm | ||||
| 			}, | ||||
| 			(err, token) => { | ||||
| 				if (err) return rej(err); | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import { Request, Response, Router } from "express"; | ||||
| import Config from "../../util/Config"; | ||||
| import { trimSpecial, User, Snowflake, UserModel } from "@fosscord/server-util"; | ||||
| import { trimSpecial, User, Snowflake, UserModel, Config } from "@fosscord/server-util"; | ||||
| import bcrypt from "bcrypt"; | ||||
| import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "../../util/instanceOf"; | ||||
| import "missing-native-js-functions"; | ||||
| @ -21,7 +20,7 @@ router.post( | ||||
| 		$invite: String, | ||||
| 		$date_of_birth: Date, // "2000-04-03"
 | ||||
| 		$gift_code_sku_id: String, | ||||
| 		$captcha_key: String, | ||||
| 		$captcha_key: String | ||||
| 	}), | ||||
| 	async (req: Request, res: Response) => { | ||||
| 		const { | ||||
| @ -33,14 +32,14 @@ router.post( | ||||
| 			invite, | ||||
| 			date_of_birth, | ||||
| 			gift_code_sku_id, // ? what is this
 | ||||
| 			captcha_key, | ||||
| 			captcha_key | ||||
| 		} = req.body; | ||||
| 		// TODO: automatically join invite
 | ||||
| 		// TODO: gift_code_sku_id?
 | ||||
| 		// TODO: check password strength
 | ||||
| 
 | ||||
| 		// adjusted_email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick
 | ||||
| 		let adjusted_email: string | undefined = adjustEmail(email); | ||||
| 		let adjusted_email: string | null = adjustEmail(email); | ||||
| 
 | ||||
| 		// adjusted_password will be the hash of the password
 | ||||
| 		let adjusted_password: string = ""; | ||||
| @ -57,21 +56,21 @@ router.post( | ||||
| 		// check if registration is allowed
 | ||||
| 		if (!register.allowNewRegistration) { | ||||
| 			throw FieldErrors({ | ||||
| 				email: { code: "REGISTRATION_DISABLED", message: req.t("auth:register.REGISTRATION_DISABLED") }, | ||||
| 				email: { code: "REGISTRATION_DISABLED", message: req.t("auth:register.REGISTRATION_DISABLED") } | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		// check if the user agreed to the Terms of Service
 | ||||
| 		if (!consent) { | ||||
| 			throw FieldErrors({ | ||||
| 				consent: { code: "CONSENT_REQUIRED", message: req.t("auth:register.CONSENT_REQUIRED") }, | ||||
| 				consent: { code: "CONSENT_REQUIRED", message: req.t("auth:register.CONSENT_REQUIRED") } | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		// require invite to register -> e.g. for organizations to send invites to their employees
 | ||||
| 		if (register.requireInvite && !invite) { | ||||
| 			throw FieldErrors({ | ||||
| 				email: { code: "INVITE_ONLY", message: req.t("auth:register.INVITE_ONLY") }, | ||||
| 				email: { code: "INVITE_ONLY", message: req.t("auth:register.INVITE_ONLY") } | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| @ -86,19 +85,19 @@ router.post( | ||||
| 				throw FieldErrors({ | ||||
| 					email: { | ||||
| 						code: "EMAIL_ALREADY_REGISTERED", | ||||
| 						message: req.t("auth.register.EMAIL_ALREADY_REGISTERED"), | ||||
| 					}, | ||||
| 						message: req.t("auth:register.EMAIL_ALREADY_REGISTERED") | ||||
| 					} | ||||
| 				}); | ||||
| 			} | ||||
| 		} else if (register.email.required) { | ||||
| 		} else if (register.email.necessary) { | ||||
| 			throw FieldErrors({ | ||||
| 				email: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") }, | ||||
| 				email: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		if (register.dateOfBirth.required && !date_of_birth) { | ||||
| 		if (register.dateOfBirth.necessary && !date_of_birth) { | ||||
| 			throw FieldErrors({ | ||||
| 				date_of_birth: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") }, | ||||
| 				date_of_birth: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } | ||||
| 			}); | ||||
| 		} else if (register.dateOfBirth.minimum) { | ||||
| 			const minimum = new Date(); | ||||
| @ -109,8 +108,8 @@ router.post( | ||||
| 				throw FieldErrors({ | ||||
| 					date_of_birth: { | ||||
| 						code: "DATE_OF_BIRTH_UNDERAGE", | ||||
| 						message: req.t("auth:register.DATE_OF_BIRTH_UNDERAGE", { years: register.dateOfBirth.minimum }), | ||||
| 					}, | ||||
| 						message: req.t("auth:register.DATE_OF_BIRTH_UNDERAGE", { years: register.dateOfBirth.minimum }) | ||||
| 					} | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| @ -123,8 +122,8 @@ router.post( | ||||
| 				throw FieldErrors({ | ||||
| 					email: { | ||||
| 						code: "EMAIL_ALREADY_REGISTERED", | ||||
| 						message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"), | ||||
| 					}, | ||||
| 						message: req.t("auth:register.EMAIL_ALREADY_REGISTERED") | ||||
| 					} | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| @ -135,7 +134,7 @@ router.post( | ||||
| 				return res.status(400).json({ | ||||
| 					captcha_key: ["captcha-required"], | ||||
| 					captcha_sitekey: sitekey, | ||||
| 					captcha_service: service, | ||||
| 					captcha_service: service | ||||
| 				}); | ||||
| 			} | ||||
| 
 | ||||
| @ -160,8 +159,8 @@ router.post( | ||||
| 			throw FieldErrors({ | ||||
| 				username: { | ||||
| 					code: "USERNAME_TOO_MANY_USERS", | ||||
| 					message: req.t("auth:register.USERNAME_TOO_MANY_USERS"), | ||||
| 				}, | ||||
| 					message: req.t("auth:register.USERNAME_TOO_MANY_USERS") | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| @ -181,17 +180,19 @@ router.post( | ||||
| 			mobile: false, | ||||
| 			premium: false, | ||||
| 			premium_type: 0, | ||||
| 			phone: undefined, | ||||
| 			phone: null, | ||||
| 			mfa_enabled: false, | ||||
| 			verified: false, | ||||
| 			disabled: false, | ||||
| 			deleted: false, | ||||
| 			presence: { | ||||
| 				activities: [], | ||||
| 				client_status: { | ||||
| 					desktop: undefined, | ||||
| 					mobile: undefined, | ||||
| 					web: undefined, | ||||
| 					web: undefined | ||||
| 				}, | ||||
| 				status: "offline", | ||||
| 				status: "offline" | ||||
| 			}, | ||||
| 			email: adjusted_email, | ||||
| 			nsfw_allowed: true, // TODO: depending on age
 | ||||
| @ -203,7 +204,7 @@ router.post( | ||||
| 				valid_tokens_since: new Date(), | ||||
| 				relationships: [], | ||||
| 				connected_accounts: [], | ||||
| 				fingerprints: [], | ||||
| 				fingerprints: [] | ||||
| 			}, | ||||
| 			user_settings: { | ||||
| 				afk_timeout: 300, | ||||
| @ -216,7 +217,7 @@ router.post( | ||||
| 					emoji_id: null, | ||||
| 					emoji_name: null, | ||||
| 					expires_at: null, | ||||
| 					text: null, | ||||
| 					text: null | ||||
| 				}, | ||||
| 				default_guilds_restricted: false, | ||||
| 				detect_platform_accounts: true, | ||||
| @ -241,9 +242,9 @@ router.post( | ||||
| 				status: "offline", | ||||
| 				stream_notifications_enabled: true, | ||||
| 				theme: "dark", | ||||
| 				timezone_offset: 0, | ||||
| 				timezone_offset: 0 | ||||
| 				// timezone_offset: // TODO: timezone from request
 | ||||
| 			}, | ||||
| 			} | ||||
| 		}; | ||||
| 
 | ||||
| 		// insert user into database
 | ||||
| @ -253,7 +254,7 @@ router.post( | ||||
| 	} | ||||
| ); | ||||
| 
 | ||||
| export function adjustEmail(email: string): string | undefined { | ||||
| export function adjustEmail(email: string): string | null { | ||||
| 	// body parser already checked if it is a valid email
 | ||||
| 	const parts = <RegExpMatchArray>email.match(EMAIL_REGEX); | ||||
| 	// @ts-ignore
 | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| import { Router } from "express"; | ||||
| import { ChannelModel, getPermission, MessageDeleteBulkEvent, MessageModel } from "@fosscord/server-util"; | ||||
| import { ChannelModel, Config, getPermission, MessageDeleteBulkEvent, MessageModel } from "@fosscord/server-util"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import Config from "../../../../util/Config"; | ||||
| import { emitEvent } from "../../../../util/Event"; | ||||
| import { check } from "../../../../util/instanceOf"; | ||||
| 
 | ||||
|  | ||||
| @ -71,9 +71,11 @@ router.get("/", async (req, res) => { | ||||
| 			id: { $gt: (BigInt(around) - BigInt(halfLimit)).toString(), $lt: (BigInt(around) + BigInt(halfLimit)).toString() } | ||||
| 		}); | ||||
| 	else { | ||||
| 		query = MessageModel.find({ channel_id }).sort({ id: -1 }); | ||||
| 		query = MessageModel.find({ channel_id }); | ||||
| 	} | ||||
| 
 | ||||
| 	query = query.sort({ id: -1 }); | ||||
| 
 | ||||
| 	const messages = await query.limit(limit).exec(); | ||||
| 
 | ||||
| 	return res.json( | ||||
|  | ||||
| @ -1,6 +1,13 @@ | ||||
| import { ChannelModel, ChannelPinsUpdateEvent, getPermission, MessageModel, MessageUpdateEvent, toObject } from "@fosscord/server-util"; | ||||
| import { | ||||
| 	ChannelModel, | ||||
| 	ChannelPinsUpdateEvent, | ||||
| 	Config, | ||||
| 	getPermission, | ||||
| 	MessageModel, | ||||
| 	MessageUpdateEvent, | ||||
| 	toObject | ||||
| } from "@fosscord/server-util"; | ||||
| import { Router, Request, Response } from "express"; | ||||
| import Config from "../../../util/Config"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import { emitEvent } from "../../../util/Event"; | ||||
| 
 | ||||
|  | ||||
| @ -1,12 +1,11 @@ | ||||
| import { Config } from "@fosscord/server-util"; | ||||
| import { Router } from "express"; | ||||
| import Config from "../util/Config"; | ||||
| 
 | ||||
| const router = Router(); | ||||
| 
 | ||||
| router.get("/", (req, res) => { | ||||
| 	const endpoint = Config.getAll()?.gateway?.endpoint; | ||||
| 
 | ||||
| 	res.send({ url: endpoint || "ws://localhost:3002" }); | ||||
| 	const { endpoint } = Config.get().gateway; | ||||
| 	res.send({ url: endpoint || process.env.GATEWAY || "ws://localhost:3002" }); | ||||
| }); | ||||
| 
 | ||||
| export default router; | ||||
|  | ||||
| @ -1,9 +1,8 @@ | ||||
| import { Router, Request, Response } from "express"; | ||||
| import { RoleModel, GuildModel, Snowflake, Guild, RoleDocument } from "@fosscord/server-util"; | ||||
| import { RoleModel, GuildModel, Snowflake, Guild, RoleDocument, Config } from "@fosscord/server-util"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import { check } from "./../../util/instanceOf"; | ||||
| import { GuildCreateSchema } from "../../schema/Guild"; | ||||
| import Config from "../../util/Config"; | ||||
| import { getPublicUser } from "../../util/User"; | ||||
| import { addMember } from "../../util/Member"; | ||||
| import { createChannel } from "../../util/Channel"; | ||||
|  | ||||
| @ -1,11 +1,10 @@ | ||||
| import { Request, Response, Router } from "express"; | ||||
| const router: Router = Router(); | ||||
| import { TemplateModel, GuildModel, toObject, UserModel, RoleModel, Snowflake, Guild } from "@fosscord/server-util"; | ||||
| import { TemplateModel, GuildModel, toObject, UserModel, RoleModel, Snowflake, Guild, Config } from "@fosscord/server-util"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import { GuildTemplateCreateSchema } from "../../../schema/Guild"; | ||||
| import { getPublicUser } from "../../../util/User"; | ||||
| import { check } from "../../../util/instanceOf"; | ||||
| import Config from "../../../util/Config"; | ||||
| import { addMember } from "../../../util/Member"; | ||||
| 
 | ||||
| router.get("/:code", async (req: Request, res: Response) => { | ||||
| @ -37,7 +36,7 @@ router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res | ||||
| 		...body, | ||||
| 		...template.serialized_source_guild, | ||||
| 		id: guild_id, | ||||
| 		owner_id: req.user_id, | ||||
| 		owner_id: req.user_id | ||||
| 	}; | ||||
| 
 | ||||
| 	const [guild_doc, role] = await Promise.all([ | ||||
| @ -52,8 +51,8 @@ router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res | ||||
| 			name: "@everyone", | ||||
| 			permissions: 2251804225n, | ||||
| 			position: 0, | ||||
| 			tags: null, | ||||
| 		}).save(), | ||||
| 			tags: null | ||||
| 		}).save() | ||||
| 	]); | ||||
| 
 | ||||
| 	await addMember(req.user_id, guild_id, { guild: guild_doc }); | ||||
|  | ||||
							
								
								
									
										30
									
								
								src/routes/users/@me/delete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/routes/users/@me/delete.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| import { Router, Request, Response } from "express"; | ||||
| import { UserModel,UserDocument, toObject } from "@fosscord/server-util"; | ||||
| import { getPublicUser } from "../../../util/User"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import { UserUpdateSchema } from "../../../schema/User"; | ||||
| import { check, FieldErrors, Length } from "../../../util/instanceOf"; | ||||
| import { db } from "@fosscord/server-util"; | ||||
| import bcrypt from "bcrypt"; | ||||
| const router = Router(); | ||||
| 
 | ||||
| router.post("/", async (req: Request, res: Response) => { | ||||
| 
 | ||||
| 	const user = await UserModel.findOne( | ||||
| 		{ id: req.user_id }, | ||||
| 		 | ||||
| 	).exec();  //User object
 | ||||
| 	 | ||||
| 	let correctpass = await bcrypt.compare(req.body.password,user!.user_data.hash) //Not sure if user typed right password :/
 | ||||
|     if(correctpass){ | ||||
| 	await UserModel.deleteOne({id: req.user_id}).exec() //Yeetus user deletus
 | ||||
| 
 | ||||
| 	res.sendStatus(204); | ||||
| 	} | ||||
| 	else{ | ||||
| 		res.sendStatus(401); | ||||
| 
 | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| export default router; | ||||
							
								
								
									
										10
									
								
								src/routes/users/@me/disable.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/routes/users/@me/disable.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| import { Router } from "express"; | ||||
| 
 | ||||
| const router = Router(); | ||||
| 
 | ||||
| router.post("/", (req, res) => { | ||||
| 	// TODO:
 | ||||
| 	res.sendStatus(204); | ||||
| }); | ||||
| 
 | ||||
| export default router; | ||||
| @ -7,9 +7,9 @@ config(); | ||||
| import { FosscordServer } from "./Server"; | ||||
| import cluster from "cluster"; | ||||
| import os from "os"; | ||||
| const cores = os.cpus().length; | ||||
| const cores = Number(process.env.threads) || os.cpus().length; | ||||
| 
 | ||||
| if (cluster.isMaster && process.env.production == "true") { | ||||
| if (cluster.isMaster && process.env.NODE_ENV == "production") { | ||||
| 	console.log(`Primary ${process.pid} is running`); | ||||
| 
 | ||||
| 	// Fork workers.
 | ||||
| @ -22,8 +22,7 @@ if (cluster.isMaster && process.env.production == "true") { | ||||
| 		cluster.fork(); | ||||
| 	}); | ||||
| } else { | ||||
| 	var port = Number(process.env.PORT); | ||||
| 	if (isNaN(port)) port = 3001; | ||||
| 	var port = Number(process.env.PORT) || 3001; | ||||
| 
 | ||||
| 	const server = new FosscordServer({ port }); | ||||
| 	server.start().catch(console.error); | ||||
|  | ||||
| @ -1,19 +1,7 @@ | ||||
| import { Config, Snowflake } from "@fosscord/server-util"; | ||||
| import crypto from "crypto"; | ||||
| 
 | ||||
| export default { | ||||
| 	init() { | ||||
| 		return Config.init({ api: DefaultOptions }); | ||||
| 	}, | ||||
| 	get(): DefaultOptions { | ||||
| 		return Config.getAll().api; | ||||
| 	}, | ||||
| 	set(val: any) { | ||||
| 		return Config.setAll({ api: val }); | ||||
| 	}, | ||||
| 	getAll: Config.getAll, | ||||
| 	setAll: Config.setAll, | ||||
| }; | ||||
| // @ts-nocheck
 | ||||
| import Ajv, { JSONSchemaType } from "ajv"; | ||||
| import { getConfigPathForFile } from "@fosscord/server-util/dist/util/Config"; | ||||
| import { Config } from "@fosscord/server-util"; | ||||
| 
 | ||||
| export interface RateLimitOptions { | ||||
| 	count: number; | ||||
| @ -21,6 +9,7 @@ export interface RateLimitOptions { | ||||
| } | ||||
| 
 | ||||
| export interface DefaultOptions { | ||||
| 	gateway: string; | ||||
| 	general: { | ||||
| 		instance_id: string; | ||||
| 	}; | ||||
| @ -64,7 +53,7 @@ export interface DefaultOptions { | ||||
| 					login?: RateLimitOptions; | ||||
| 					register?: RateLimitOptions; | ||||
| 				}; | ||||
| 				channel?: {}; | ||||
| 				channel?: string; | ||||
| 				// TODO: rate limit configuration for all routes
 | ||||
| 			}; | ||||
| 		}; | ||||
| @ -84,13 +73,13 @@ export interface DefaultOptions { | ||||
| 	}; | ||||
| 	register: { | ||||
| 		email: { | ||||
| 			required: boolean; | ||||
| 			necessary: boolean; | ||||
| 			allowlist: boolean; | ||||
| 			blocklist: boolean; | ||||
| 			domains: string[]; | ||||
| 		}; | ||||
| 		dateOfBirth: { | ||||
| 			required: boolean; | ||||
| 			necessary: boolean; | ||||
| 			minimum: number; // in years
 | ||||
| 		}; | ||||
| 		requireCaptcha: boolean; | ||||
| @ -107,85 +96,277 @@ export interface DefaultOptions { | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| export const DefaultOptions: DefaultOptions = { | ||||
| 	general: { | ||||
| 		instance_id: Snowflake.generate(), | ||||
| 	}, | ||||
| 	permissions: { | ||||
| 		user: { | ||||
| 			createGuilds: true, | ||||
| 		}, | ||||
| 	}, | ||||
| 	limits: { | ||||
| 		user: { | ||||
| 			maxGuilds: 100, | ||||
| 			maxUsername: 32, | ||||
| 			maxFriends: 1000, | ||||
| 		}, | ||||
| 		guild: { | ||||
| 			maxRoles: 250, | ||||
| 			maxMembers: 250000, | ||||
| 			maxChannels: 500, | ||||
| 			maxChannelsInCategory: 50, | ||||
| 			hideOfflineMember: 1000, | ||||
| 		}, | ||||
| 		message: { | ||||
| 			characters: 2000, | ||||
| 			ttsCharacters: 200, | ||||
| 			maxReactions: 20, | ||||
| 			maxAttachmentSize: 8388608, | ||||
| 			maxBulkDelete: 100, | ||||
| 		}, | ||||
| 		channel: { | ||||
| 			maxPins: 50, | ||||
| 			maxTopic: 1024, | ||||
| 		}, | ||||
| 		rate: { | ||||
| 			ip: { | ||||
| 				enabled: true, | ||||
| 				count: 1000, | ||||
| 				timespan: 1000 * 60 * 10, | ||||
| const schema: JSONSchemaType<DefaultOptions> & { | ||||
| 	definitions: { | ||||
| 		rateLimitOptions: JSONSchemaType<RateLimitOptions>; | ||||
| 	}; | ||||
| } = { | ||||
| 	type: "object", | ||||
| 	definitions: { | ||||
| 		rateLimitOptions: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				count: { type: "number" }, | ||||
| 				timespan: { type: "number" } | ||||
| 			}, | ||||
| 			routes: {}, | ||||
| 		}, | ||||
| 			required: ["count", "timespan"] | ||||
| 		} | ||||
| 	}, | ||||
| 	security: { | ||||
| 		jwtSecret: crypto.randomBytes(256).toString("base64"), | ||||
| 		forwadedFor: null, | ||||
| 		// forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
 | ||||
| 		// forwadedFor: "CF-Connecting-IP" // cloudflare:
 | ||||
| 		captcha: { | ||||
| 			enabled: false, | ||||
| 			service: null, | ||||
| 			sitekey: null, | ||||
| 			secret: null, | ||||
| 		}, | ||||
| 	}, | ||||
| 	login: { | ||||
| 		requireCaptcha: false, | ||||
| 	}, | ||||
| 	register: { | ||||
| 		email: { | ||||
| 			required: true, | ||||
| 			allowlist: false, | ||||
| 			blocklist: true, | ||||
| 			domains: [], // TODO: efficiently save domain blocklist in database
 | ||||
| 			// domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
 | ||||
| 		}, | ||||
| 		dateOfBirth: { | ||||
| 			required: true, | ||||
| 			minimum: 13, | ||||
| 		}, | ||||
| 		requireInvite: false, | ||||
| 		requireCaptcha: true, | ||||
| 		allowNewRegistration: true, | ||||
| 		allowMultipleAccounts: true, | ||||
| 		password: { | ||||
| 			minLength: 8, | ||||
| 			minNumbers: 2, | ||||
| 			minUpperCase: 2, | ||||
| 			minSymbols: 0, | ||||
| 			blockInsecureCommonPasswords: false, | ||||
| 	properties: { | ||||
| 		gateway: { | ||||
| 			type: "string" | ||||
| 		}, | ||||
| 		general: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				instance_id: { | ||||
| 					type: "string" | ||||
| 				} | ||||
| 			}, | ||||
| 			required: ["instance_id"], | ||||
| 			additionalProperties: false | ||||
| 		}, | ||||
| 		permissions: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				user: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						createGuilds: { | ||||
| 							type: "boolean" | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["createGuilds"], | ||||
| 					additionalProperties: false | ||||
| 				} | ||||
| 			}, | ||||
| 			required: ["user"], | ||||
| 			additionalProperties: false | ||||
| 		}, | ||||
| 		limits: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				user: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						maxFriends: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxGuilds: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxUsername: { | ||||
| 							type: "number" | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["maxFriends", "maxGuilds", "maxUsername"], | ||||
| 					additionalProperties: false | ||||
| 				}, | ||||
| 				guild: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						maxRoles: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxMembers: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxChannels: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxChannelsInCategory: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						hideOfflineMember: { | ||||
| 							type: "number" | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["maxRoles", "maxMembers", "maxChannels", "maxChannelsInCategory", "hideOfflineMember"], | ||||
| 					additionalProperties: false | ||||
| 				}, | ||||
| 				message: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						characters: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						ttsCharacters: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxReactions: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxAttachmentSize: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxBulkDelete: { | ||||
| 							type: "number" | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["characters", "ttsCharacters", "maxReactions", "maxAttachmentSize", "maxBulkDelete"], | ||||
| 					additionalProperties: false | ||||
| 				}, | ||||
| 				channel: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						maxPins: { | ||||
| 							type: "number" | ||||
| 						}, | ||||
| 						maxTopic: { | ||||
| 							type: "number" | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["maxPins", "maxTopic"], | ||||
| 					additionalProperties: false | ||||
| 				}, | ||||
| 				rate: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						ip: { | ||||
| 							type: "object", | ||||
| 							properties: { | ||||
| 								enabled: { type: "boolean" }, | ||||
| 								count: { type: "number" }, | ||||
| 								timespan: { type: "number" } | ||||
| 							}, | ||||
| 							required: ["enabled", "count", "timespan"], | ||||
| 							additionalProperties: false | ||||
| 						}, | ||||
| 						routes: { | ||||
| 							type: "object", | ||||
| 							properties: { | ||||
| 								auth: { | ||||
| 									type: "object", | ||||
| 									properties: { | ||||
| 										login: { $ref: "#/definitions/rateLimitOptions" }, | ||||
| 										register: { $ref: "#/definitions/rateLimitOptions" } | ||||
| 									}, | ||||
| 									nullable: true, | ||||
| 									required: [], | ||||
| 									additionalProperties: false | ||||
| 								}, | ||||
| 								channel: { | ||||
| 									type: "string", | ||||
| 									nullable: true | ||||
| 								} | ||||
| 							}, | ||||
| 							required: [], | ||||
| 							additionalProperties: false | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["ip", "routes"] | ||||
| 				} | ||||
| 			}, | ||||
| 			required: ["channel", "guild", "message", "rate", "user"], | ||||
| 			additionalProperties: false | ||||
| 		}, | ||||
| 		security: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				jwtSecret: { | ||||
| 					type: "string" | ||||
| 				}, | ||||
| 				forwadedFor: { | ||||
| 					type: "string", | ||||
| 					nullable: true | ||||
| 				}, | ||||
| 				captcha: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						enabled: { type: "boolean" }, | ||||
| 						service: { | ||||
| 							type: "string", | ||||
| 							enum: ["hcaptcha", "recaptcha", null], | ||||
| 							nullable: true | ||||
| 						}, | ||||
| 						sitekey: { | ||||
| 							type: "string", | ||||
| 							nullable: true | ||||
| 						}, | ||||
| 						secret: { | ||||
| 							type: "string", | ||||
| 							nullable: true | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["enabled", "secret", "service", "sitekey"], | ||||
| 					additionalProperties: false | ||||
| 				} | ||||
| 			}, | ||||
| 			required: ["captcha", "forwadedFor", "jwtSecret"], | ||||
| 			additionalProperties: false | ||||
| 		}, | ||||
| 		login: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				requireCaptcha: { type: "boolean" } | ||||
| 			}, | ||||
| 			required: ["requireCaptcha"], | ||||
| 			additionalProperties: false | ||||
| 		}, | ||||
| 		register: { | ||||
| 			type: "object", | ||||
| 			properties: { | ||||
| 				email: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						necessary: { type: "boolean" }, | ||||
| 						allowlist: { type: "boolean" }, | ||||
| 						blocklist: { type: "boolean" }, | ||||
| 						domains: { | ||||
| 							type: "array", | ||||
| 							items: { | ||||
| 								type: "string" | ||||
| 							} | ||||
| 						} | ||||
| 					}, | ||||
| 					required: ["allowlist", "blocklist", "domains", "necessary"], | ||||
| 					additionalProperties: false | ||||
| 				}, | ||||
| 				dateOfBirth: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						necessary: { type: "boolean" }, | ||||
| 						minimum: { type: "number" } | ||||
| 					}, | ||||
| 					required: ["minimum", "necessary"], | ||||
| 					additionalProperties: false | ||||
| 				}, | ||||
| 				requireCaptcha: { type: "boolean" }, | ||||
| 				requireInvite: { type: "boolean" }, | ||||
| 				allowNewRegistration: { type: "boolean" }, | ||||
| 				allowMultipleAccounts: { type: "boolean" }, | ||||
| 				password: { | ||||
| 					type: "object", | ||||
| 					properties: { | ||||
| 						minLength: { type: "number" }, | ||||
| 						minNumbers: { type: "number" }, | ||||
| 						minUpperCase: { type: "number" }, | ||||
| 						minSymbols: { type: "number" }, | ||||
| 						blockInsecureCommonPasswords: { type: "boolean" } | ||||
| 					}, | ||||
| 					required: ["minLength", "minNumbers", "minUpperCase", "minSymbols", "blockInsecureCommonPasswords"], | ||||
| 					additionalProperties: false | ||||
| 				} | ||||
| 			}, | ||||
| 			required: [ | ||||
| 				"allowMultipleAccounts", | ||||
| 				"allowNewRegistration", | ||||
| 				"dateOfBirth", | ||||
| 				"email", | ||||
| 				"password", | ||||
| 				"requireCaptcha", | ||||
| 				"requireInvite" | ||||
| 			], | ||||
| 			additionalProperties: false | ||||
| 		} | ||||
| 	}, | ||||
| 	required: ["gateway", "general", "limits", "login", "permissions", "register", "security"], | ||||
| 	additionalProperties: false | ||||
| }; | ||||
| 
 | ||||
| const ajv = new Ajv(); | ||||
| const validator = ajv.compile(schema); | ||||
| 
 | ||||
| const configPath = getConfigPathForFile("fosscord", "api", ".json"); | ||||
| 
 | ||||
| export const apiConfig = new Config<DefaultOptions>({ path: configPath, schemaValidator: validator, schema: schema }); | ||||
|  | ||||
| @ -10,11 +10,11 @@ import { | ||||
| 	RoleModel, | ||||
| 	toObject, | ||||
| 	UserModel, | ||||
| 	GuildDocument | ||||
| 	GuildDocument, | ||||
| 	Config | ||||
| } from "@fosscord/server-util"; | ||||
| 
 | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import Config from "./Config"; | ||||
| import { emitEvent } from "./Event"; | ||||
| import { getPublicUser } from "./User"; | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { Config } from "@fosscord/server-util"; | ||||
| import "missing-native-js-functions"; | ||||
| import Config from "./Config"; | ||||
| 
 | ||||
| const reNUMBER = /[0-9]/g; | ||||
| const reUPPERCASELETTER = /[A-Z]/g; | ||||
| @ -17,13 +17,7 @@ const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored | ||||
|  * Returns: 0 > pw > 1 | ||||
|  */ | ||||
| export function check(password: string): number { | ||||
| 	const { | ||||
| 		minLength, | ||||
| 		minNumbers, | ||||
| 		minUpperCase, | ||||
| 		minSymbols, | ||||
| 		blockInsecureCommonPasswords, | ||||
| 	} = Config.get().register.password; | ||||
| 	const { minLength, minNumbers, minUpperCase, minSymbols } = Config.get().register.password; | ||||
| 	var strength = 0; | ||||
| 
 | ||||
| 	// checks for total password len
 | ||||
| @ -51,10 +45,5 @@ export function check(password: string): number { | ||||
| 		strength = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (blockInsecureCommonPasswords) { | ||||
| 		if (blocklist.includes(password)) { | ||||
| 			strength = 0; | ||||
| 		} | ||||
| 	} | ||||
| 	return strength; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Flam3rboy
						Flam3rboy