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